<?xml version="1.0" encoding="utf-8"?>
<!-- generator="FeedCreator 1.7.2-ppt DokuWiki" -->
<?xml-stylesheet href="http://www.pic24.ru/lib/exe/css.php?s=feed" type="text/css"?>
<rdf:RDF
    xmlns="http://purl.org/rss/1.0/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel rdf:about="http://www.pic24.ru/feed.php">
        <title>PIC24 en:osa:articles</title>
        <description></description>
        <link>http://www.pic24.ru/</link>
        <image rdf:resource="http://www.pic24.ru/lib/images/favicon.ico" />
       <dc:date>2023-02-10T11:03:16+03:00</dc:date>
        <items>
            <rdf:Seq>
                <rdf:li rdf:resource="http://www.pic24.ru/doku.php/en/osa/articles/pk2_osa_piano?rev=1239866353"/>
                <rdf:li rdf:resource="http://www.pic24.ru/doku.php/en/osa/articles/vga_game?rev=1262545739"/>
                <rdf:li rdf:resource="http://www.pic24.ru/doku.php/en/osa/articles/vga_terminal?rev=1316766129"/>
            </rdf:Seq>
        </items>
    </channel>
    <image rdf:about="http://www.pic24.ru/lib/images/favicon.ico">
        <title>PIC24</title>
        <link>http://www.pic24.ru/</link>
        <url>http://www.pic24.ru/lib/images/favicon.ico</url>
    </image>
    <item rdf:about="http://www.pic24.ru/doku.php/en/osa/articles/pk2_osa_piano?rev=1239866353">
        <dc:format>text/html</dc:format>
        <dc:date>2009-04-16T11:19:13+03:00</dc:date>
        <title>&quot;Piano&quot; with RTOS</title>
        <link>http://www.pic24.ru/doku.php/en/osa/articles/pk2_osa_piano?rev=1239866353</link>
        <description>


&lt;h1&gt;&lt;a name=&quot;piano_with_rtos&quot; id=&quot;piano_with_rtos&quot;&gt;&amp;quot;Piano&amp;quot; with RTOS&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;p&gt;

&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano.jpg?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano.jpg&quot; class=&quot;media&quot; title=&quot;pk2_osa_piano.jpg&quot; alt=&quot;pk2_osa_piano.jpg&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Piano with RTOS&quot; [1-60] --&gt;
&lt;h2&gt;&lt;a name=&quot;intro&quot; id=&quot;intro&quot;&gt;Intro&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

&lt;span class=&quot;important&quot;&gt;(Sorry for my appalling english)&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;
This arcticle describes a possibility of ADC usage to read touch sence buttons. As example we will encode program &amp;quot;Piano&amp;quot; for working with 36 capacitive sensing buttons (3 octaves). To avoid bore, we will make it polyphonic. For our project we will use demo-boards from PicKit2 kits based on PIC16F690, PIC16F886 or PIC16F887. In addition we use PIC16F88.
&lt;/p&gt;

&lt;p&gt;
Here is two minutes demonstration video (sorry for my bad piano play).
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Intro&quot; [61-546] --&gt;
&lt;h3&gt;&lt;a name=&quot;hq_video_34_mb&quot; id=&quot;hq_video_34_mb&quot;&gt;HQ video (34 Mb)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

&lt;div align=center&gt;
&lt;object width=&quot;640&quot; height=&quot;480&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/Ii7-orwG8F0&amp;hl=en&amp;fs=1&amp;rel=0&quot;&gt;&lt;/param&gt;
&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;

&lt;embed src=&quot;http://www.youtube.com/v/Ii7-orwG8F0&amp;hl=en&amp;fs=1&amp;rel=0&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; width=&quot;640&quot; height=&quot;480&quot;&gt;&lt;/embed&gt;

&lt;/object&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;HQ video (34 Mb)&quot; [547-967] --&gt;
&lt;h3&gt;&lt;a name=&quot;lq_video_6.3_mb&quot; id=&quot;lq_video_6.3_mb&quot;&gt;LQ video (6.3 Mb)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

&lt;div align=center&gt;
&lt;object width=&quot;320&quot; height=&quot;240&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/1oic1seP8u8&amp;hl=en&amp;fs=1&amp;rel=0&quot;&gt;&lt;/param&gt;
&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;

&lt;embed src=&quot;http://www.youtube.com/v/1oic1seP8u8&amp;hl=en&amp;fs=1&amp;rel=0&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; width=&quot;320&quot; height=&quot;240&quot;&gt;&lt;/embed&gt;

&lt;/object&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;LQ video (6.3 Mb)&quot; [968-1386] --&gt;
&lt;h2&gt;&lt;a name=&quot;theory&quot; id=&quot;theory&quot;&gt;Theory&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Theory&quot; [1387-1406] --&gt;
&lt;h3&gt;&lt;a name=&quot;capacitive_sensing&quot; id=&quot;capacitive_sensing&quot;&gt;Capacitive sensing&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Capacitive sensing principles are described &lt;a href=&quot;http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=2600&amp;amp;param=en535168&quot; class=&quot;urlextern&quot; title=&quot;http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=2600&amp;amp;param=en535168&quot;  rel=&quot;nofollow&quot;&gt;here&lt;/a&gt;. When we touch couper pad by finger, we increase scheme capacitance. The controller can detect capacitance increasing. In this case couper pad is used as capacitive sensor (like capacitor with small capacitance). If we will charge this capacitor with constant current, then voltage will increase in inverse proportion to capacity. Let&amp;#039;s assume that we make measures of voltage on capacitor at the same times after start of charging. It is evident that low-capacity capacitor will have charged less than the capacitor of large capacity. Look at the picture:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_u_t_iconst.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_u_t_iconst.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_u_t_iconst.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Two capacitors C1 and C2 (capacitance of C1 is less then capacitance of C2) are charged with the same current. At the time t0 voltage at C1 increased by more than at C2. We know that touching couper pad by finger will increase capacitance. Imagine that we periodically charge/discharge capacitor (capacitive sensor) and makes measurings of voltage every time with same delay after start. While capacitance of sensor remain unchanged, we will read the same voltage&amp;#039;s value. But when we will touch sensor by finger, the capacitance will increase and voltage will decrease. Thus we can detect the touching.
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;This principle of reading voltage on capacitive sensor after the same delay after start of charging we will use to read our touch buttons.&lt;/strong&gt;
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;implementation&quot; id=&quot;implementation&quot;&gt;Implementation&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

We need four things: 
&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; a capacitive sensor;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; a current source;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; a precise delay;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; a voltage meter.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

First of all we need a &lt;strong&gt;capacitive sensor&lt;/strong&gt;. We can use any metal plate, e.g. a coin.
&lt;/p&gt;

&lt;p&gt;
Now we need a &lt;strong&gt;current source&lt;/strong&gt;. Ideally, it must be a source of constant current. Is there any way to simplify this requirement? Can we apply just a RC-circuit? Look at the picture:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_u_t_.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_u_t_.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_u_t_.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Capacitors C1 and C2 (C1 &amp;lt; C2) are in RC-circuit with the identical values of resistance. It is obviously that C1 will be charged faster than C2. The charge digrams are not linear, however we can determine in which case the capacitance is larger, because of at the time t0 values of voltages are different. Thus we can use simple RC-circuits instead of current sources.
&lt;/p&gt;

&lt;p&gt;
Next we need to form a &lt;strong&gt;precise delay&lt;/strong&gt;. Due to fact that time of charging is too little, we can form this delay with empty cycle. While delay is active we have to disable interrupts to avoid increasing time of charging.
&lt;/p&gt;

&lt;p&gt;
And we will use ADC module as a &lt;strong&gt;voltage meter&lt;/strong&gt;. Look at the picture:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_u_t_measure.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_u_t_measure.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_u_t_measure.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
When we need to measure capacitance, we follow that steps:
&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; At the begin: U(Ch)=0, AIN is digital output = &amp;quot;0&amp;quot;, DOUT = &amp;quot;0&amp;quot;.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; At the point &lt;strong&gt;t&lt;/strong&gt; pin DOUT becames &amp;quot;1&amp;quot;, and pin AIN switches to analog input mode.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; At the point &lt;strong&gt;t0&lt;/strong&gt; we set GODONE = 1 to start AD convertion. Writing 1 to GODONE will disconnect internal capacitor Chold from external scheme and the voltage on Chold will be held and measured.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; After the measuring is done (at moment &lt;strong&gt;t1&lt;/strong&gt;) pin AIN switches to digital output with &amp;quot;0&amp;quot;-state to discharge Ch.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Pin DOUT set to &amp;quot;0&amp;quot; to reduce power consumption.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

As a result we have a scheme to connect one touch button:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_1button_scheme.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_1button_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_1button_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
(In out example we use 1 ruble coin as capacitive sensor). While we do not touch a coin by finger, PIC measures the Cp - sum of capacitance of analog input pin, capacitance between coin and ground, coin and other coins, between wires. When we touch coin by finger, we add capacitor Ch (human), the resulting capacity increases.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;many_buttons&quot; id=&quot;many_buttons&quot;&gt;Many buttons&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

We can to connect coins to all analog inputs of controller.
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_nbuttons_scheme.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_nbuttons_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_nbuttons_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
But thus we are limited by number of analog inputs (e.g. 7 at PIC16F88). Piano with 7 keys will be too uninteresting. We need more keys. Let&amp;#039;s try to modify our scheme to get possibility of connection more than one button per one analog input. Do do it we just add a splitting diodes:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_2buttons_scheme.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_2buttons_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_2buttons_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
As you see at the picture, we can measure capacitance of each sensor separately using only one analog input by controlling digital outputs DOUT1 and DOUT2. Thus we can connect to one analog input three, four, five or more keys. We are limitted by number of pins that can be used as digital control pins DOUTx only. 
&lt;/p&gt;

&lt;p&gt;
If we will use 6 analog inputs and 6 control digital outputs, then we can to read matrix of 6x6 = 36 capacitive sensors! As a result we have a scheme of touch buttons connecting:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_c-matrix.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_c-matrix.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_c-matrix.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
That&amp;#039;s it!
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;notes&quot; id=&quot;notes&quot;&gt;Notes&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

This method was successfully applied for work with 36-keys keyboard. But there are some disadvantages that should be prevented at the design stage.
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;temperature_drift&quot; id=&quot;temperature_drift&quot;&gt;Temperature drift&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

The capacitance of Chold and Cp and the resistance of R have the temperature drift. The speed of capacitive sensor charging will be different for different temperatures.
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_rc_temp.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_rc_temp.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_rc_temp.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Here are diagrams of RC-circuit charging for touched and untouched buttons for very different temeratures. It is visibly that speed of touched sensor charging at T1 is same as speed of untouched sensor charging. So you should remember that treshold voltage sometimes must be recounted (at least 1 time per day).
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;noise&quot; id=&quot;noise&quot;&gt;Noise&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

Our finger is a source of noise for capacitive sensor. In reality in this case capacity charging diagram will look like this:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_u_t_navodki.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_u_t_navodki.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_u_t_navodki.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Ideal diagram shown in cyan. The ideal voltage at t0 will allways eq. to Uи. Real diagram shown in blue. Real voltage value will have some deviation within Uи. Depending on interference phase on moment of start of measuring U will be greater or less than Uи. 
&lt;/p&gt;

&lt;p&gt;
This noise will not inhibit when sensor touched by finger directly, because in this case we introduce  significant additive capasitance in our scheme. But when sensor touched through some surface (e.g. glass or paper), the additive capacitance is relatively small. The speed of charge will change slightly. The presense of noise will complicate voltage drop detecting. In this case it may be nessesary to make measures several times at to take an average value for more accurate detection of button is pressed.
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;analog_input_s_capacitance&quot; id=&quot;analog_input_s_capacitance&quot;&gt;Analog input&amp;#039;s capacitance&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

All controller&amp;#039;s inputs have their own capacitance. This copacitance takes part in out measurments too. The problem is that all inputs have different capacitance, because they have different schematic solutions. This will cause different speeds of capasitor voltage rising on different pins. Thus our program should know that all input pins can have their own trigger tresholds.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Capacitive sensing&quot; [1407-8134] --&gt;
&lt;h3&gt;&lt;a name=&quot;sound_generation&quot; id=&quot;sound_generation&quot;&gt;Sound generation&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;low_frequency_meander&quot; id=&quot;low_frequency_meander&quot;&gt;Low frequency meander&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

Using meander of sound frequencies is the most common way to generate sound in embedded systems. For example to make 1KHz sound we generate 1 KHz square meander. In most applications that&amp;#039;s enough: microwave ofen tell us that food is heated, refrigerator remind us that door is not closed, ect.
&lt;/p&gt;

&lt;p&gt;
This way of sound generation is very simple and quite informative: we can generate sounds of different frequencies, durations, sequences, ect. Can we get polyphony with this method? Yes, we can. We can to generate 2 meanders on 2 controller&amp;#039;s pins, or 3 meanders on 3 controller&amp;#039;s pins, or 4 on 4, ect. And then we can mix them schematically. But this method have some disadvantages:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; is requires several pins to generate sound (8 pins for 8 channels);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; generation of two meanders is more difficult task than generation of one meander;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; sound generated by square wave is quite unpleasant.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;using_dac&quot; id=&quot;using_dac&quot;&gt;Using DAC&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

PIC controllers have not internal DAC module, bat we can use PWM module with high frequency sampling (higher than we can hear). Using DAC (PWM) we can generate any type of signal: square, triangle, sinus, ect.
&lt;/p&gt;

&lt;p&gt;
PWM generated signal is filtered by low-pass filter to suppress PWM frequency. So we have constant voltage level after filter while duty cycle will remain constant. When duty cycle get more longer, voltage level became greater. When duty cycle get shorter, voltage level becames less. It is obviously, that voltage level = 0 when duty cycle == 0; and voltage level = Vdd when duty cycle == max.
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;how_to_generate_meander_using_pwm&quot; id=&quot;how_to_generate_meander_using_pwm&quot;&gt;How to generate meander using PWM?&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

Look at the picture below:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_pwm1_en.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_pwm1_en.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_pwm1_en.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
When we need to generate &amp;quot;1&amp;quot;-state, we set duty cycle at maximum (PWM duty cycle on picture is not at maximum; this is for visibility: we see that PWM frequency more greater than meander frequency). When we need to generate &amp;quot;0&amp;quot;-state, we set duty cycle at minimum.
&lt;/p&gt;

&lt;p&gt;
PWM signal bypasses through the low-pass filter, and we get meander (green diagram). In reality frequency of PWM is more greater than frequency of signal, therefore green diagram will look more likely meander.
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;how_to_generate_2-channel_signal&quot; id=&quot;how_to_generate_2-channel_signal&quot;&gt;How to generate 2-channel signal?&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

Now we need to generate signal, which is the sum of two meanders with different frequencies. In previous example we assumed that &amp;quot;1&amp;quot;-state of meander is a maximum when generated one-channel signal. Now we assume that maximum is &amp;quot;1&amp;quot;+&amp;quot;1&amp;quot; state. Look at the picture:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_pwm2_en.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_pwm2_en.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_pwm2_en.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
We set PWM duty cycle at maximum only when both signals are at &amp;quot;1&amp;quot;-state. When only one signal in &amp;quot;1&amp;quot; state and other in &amp;quot;0&amp;quot;-state, we set PWM duty cycle at middle (50%). Green diagram shows the signal after low-pass filter.
&lt;/p&gt;

&lt;p&gt;
Now, when we know how to generate sum of 2 meanders, we can generate the sum of 3, 4, 5, ect. meanders.
&lt;/p&gt;

&lt;/div&gt;

&lt;h5&gt;&lt;a name=&quot;how_to_generate_sinus&quot; id=&quot;how_to_generate_sinus&quot;&gt;How to generate sinus?&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;level5&quot;&gt;

&lt;p&gt;

In fact, generating of sinus is the same as generating sum of meanders. We take samples at regular intervals and set PWM duty cycle according current value. For example, duty cycle will be set at maximum when we take a sample at the phase 90%; duty cycle will be set at 50% when we take a sample at the phase 0% or 180%; duty cycle will be set at 3/4 then we take a sample at the phase 30%.
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_pwm3_en.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_pwm3_en.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_pwm3_en.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Now we can generate a sum of two sinuses:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_pwm4_en.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_pwm4_en.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_pwm4_en.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
three sisuses, five sinuses, two sinuses and three meanders, ect.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Sound generation&quot; [8135-11555] --&gt;
&lt;h2&gt;&lt;a name=&quot;development&quot; id=&quot;development&quot;&gt;Development&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

So, we need to encode program &amp;quot;Piano&amp;quot; that:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; reads states of 36 touch buttons (keys);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; generates eight-channels sound.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

In addition we will add a possibility to change musical instrument by pressing a button.
&lt;/p&gt;

&lt;p&gt;
We will generate sound using internal PWM module that configured at maximum possible frequency at 8-bit resolution. We use Fosc = 20MHz, therefore PWM frequency is 78 KHz. Sound sampling rate we will set as 1/4 of PWM frequency = 19.5 KHz (we can&amp;#039;t set sampling rate higher because of 8-channel signal generating takes long time).
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Development&quot; [11556-12128] --&gt;
&lt;h3&gt;&lt;a name=&quot;tasks&quot; id=&quot;tasks&quot;&gt;Tasks&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

First of all we split program by tasks. What tasks controller solves?

&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Keyboard scanning: snans 36 touch buttons (keys);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Sound generation: forms PWM duty cycles according to pressed keys and selected musical instrument;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Button polling: waits for button pressed and select next musical instrument.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

The generation of sound is a time-critical task. Saund sample rate is 19.5 KHz, therefore we must make all mathematical operations of mixing eight channels in 50 us (250 precossor&amp;#039;s cycles). (In fact less than 50 us, because controller has to be able to do other tasks.) It is reasonable to split this task:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; &lt;strong&gt;first&lt;/strong&gt; will mix eight channel sound and form PWM duty cycle (it should be performed faster than 50 us). This task will be placed incide interrupt service routine;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; &lt;strong&gt;second&lt;/strong&gt; will form sound parameters for first task according to pressed keys (it will work in background mode).&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

Keyboard scanning and button polling are not time-critical tasks. Thus, we get three RTOS-tasks: &amp;quot;Keyboard&amp;quot;, &amp;quot;Button&amp;quot; and &amp;quot;Sound parameters maker&amp;quot;; and one non-RTOS task: &amp;quot;Synthesizer&amp;quot; - it will be placed inside ISR.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;keyboard&quot; id=&quot;keyboard&quot;&gt;&amp;quot;Keyboard&amp;quot;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

This task will scan all 36 touch buttons and form array of keys state. Besides it will inform other tasks about changing keyboard state (some keys were pressed and/or some keys were released).
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;button&quot; id=&quot;button&quot;&gt;&amp;quot;Button&amp;quot;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

This task will poll button state with debounce. This task will change musical instrument when button will be pressed.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;sound_parameters_maker&quot; id=&quot;sound_parameters_maker&quot;&gt;&amp;quot;Sound parameters maker&amp;quot;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

This task will wait message from task &amp;quot;Keyboard&amp;quot; thet keyboard state was changed. After receiving this message the task will form sound variables that tell to &amp;quot;Synthesizer&amp;quot; which channel plays sound (and parameters of sound: key number and frequency), and which channel is silent.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;synthesiser&quot; id=&quot;synthesiser&quot;&gt;&amp;quot;Synthesiser&amp;quot;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

To synthesize the sound we will create an 64-points array, that contains digitized period of sinus. To generate sound synthesizer on each execution (1 time per 51.2 us) gets next point from this array (the step depends of current channel&amp;#039;s frequency: higher frequency makes large step value, lower frequency makes short step value) and forms PWM duty cycle.
&lt;/p&gt;

&lt;p&gt;
When sinthesizer needs to play two channels, it takes two values from sinus array (each of them depends of channel frequency and current signal phase). The sum of these values is a new PWM duty cycle value. Three, four, ect. channel sound is formed in the same way.
&lt;/p&gt;

&lt;p&gt;
We will use four arrays to make possible use one of four musical instruments.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Tasks&quot; [12129-14667] --&gt;
&lt;h3&gt;&lt;a name=&quot;data&quot; id=&quot;data&quot;&gt;Data&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Here we give answer to two questions:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; What data our program will operate?&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; How data will be exchanged between tasks?&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;for_keyboard&quot; id=&quot;for_keyboard&quot;&gt;For keyboard&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

Here we need some array to store current keys state. Our piano has 36 keys, therefore we need at least five bytes array. Further, we need some variable to address any single bit in array. Simplest way is to use two variables of type char. One of them will indicate byte position in array, and another will represent mask of bit in byte.
&lt;/p&gt;

&lt;p&gt;
Besides, as said above, each analog input have it&amp;#039;s own trigger treshold. Therefore we need an array to store tresholds for each analog input. We need array of six bytes as we have 6 analog input.
&lt;/p&gt;

&lt;p&gt;
Let&amp;#039;s create a structure to hold all these data:

&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD_SIZE&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;         &lt;span class=&quot;co1&quot;&gt;// Array of bits: =1 - key pressed&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   cDataPos;               &lt;span class=&quot;co1&quot;&gt;// Two variables to point current&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   cDataMask;              &lt;span class=&quot;co1&quot;&gt;// bit while keyboard scanning.&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   Porogs&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD_COLUMNS&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;// Array of reference values of&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// ADC to determinate that key is&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// pressed&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; KBD;&lt;/pre&gt;
&lt;p&gt;
&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt; that we use constants KBD_SIZE (=6) and KBD_COLUMNS (=6) to make the possibility to increase or reduce the number of keys with minimum code modifications.&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Although I used PIC16F88, we need to take into consideration that other controllers may be used. Different controllers have different pins that can work as anlog inputs. Therefore we have to define data structure that allow us to assign different pins to be analog inputs or digital outputs. Let&amp;#039;s assume that keyboard have a form of matrix. Digital control outputs are in rows, and analog inputs are in columns. To describe digital output we need two variables: address of port register and position of bit in port. The analog input discription is a bit more complex, and here we need four variables: analog channel, address of port register, addres of tris register and position of bit in port. Thus we have two structures to describe pins:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;struct&lt;/span&gt;          &lt;span class=&quot;co1&quot;&gt;// Type for analog input (see array COLUMNS below)&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                       &lt;span class=&quot;co1&quot;&gt;//&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;  cADCChannel;  &lt;span class=&quot;co1&quot;&gt;// Analog channel&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;pPort;        &lt;span class=&quot;co1&quot;&gt;// Pointer to PORT register&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;pTris;        &lt;span class=&quot;co1&quot;&gt;// Pointer to TRIS register&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;  cMask;        &lt;span class=&quot;co1&quot;&gt;// Bit mask for PORT and TRIS&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; TColumn;
&amp;nbsp;
&lt;span class=&quot;kw4&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;struct&lt;/span&gt;          &lt;span class=&quot;co1&quot;&gt;// Type for digital control output (see array ROWS below)&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                       &lt;span class=&quot;co1&quot;&gt;//&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;pPort;        &lt;span class=&quot;co1&quot;&gt;// Pointer to PORT register&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;  cMask;        &lt;span class=&quot;co1&quot;&gt;// Bit mask for PORT&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; TRow;&lt;/pre&gt;
&lt;p&gt;
Now, using these two types we can create two arrays to assign pins as digital outputs or analof inputs.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;for_synthesizer&quot; id=&quot;for_synthesizer&quot;&gt;For synthesizer&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

To simulate different musical instruments we need four arrays, each of which will contain digitized period of signal with different freauency characteristics (see file &lt;strong&gt;sinus.c&lt;/strong&gt;). To increase speed of accessing to elements of array it is reasonable to copy current instrument (sample) into RAM. So we reserve 64 bytes in RAM to make image of current sample from ROM:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; Sample&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;&lt;/pre&gt;
&lt;p&gt;
Besides we need a variable hat indicate current sample. The choice of sample is made by task &amp;quot;Button&amp;quot;, and it is reasonable to make this variable static for this task:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; s_cCurSample;&lt;/pre&gt;
&lt;p&gt;
And last, synthesizer should know which channel plays which note (frequency and current phase of signal). Thus we have a structure:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;struct&lt;/span&gt;          &lt;span class=&quot;co1&quot;&gt;// Type for sound control variables&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt; F;     &lt;span class=&quot;co1&quot;&gt;// Frequency&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt; f;     &lt;span class=&quot;co1&quot;&gt;// Phase&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; key;  &lt;span class=&quot;co1&quot;&gt;// Played key&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; TSound;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;Data&quot; [14668-18441] --&gt;
&lt;h2&gt;&lt;a name=&quot;encoding&quot; id=&quot;encoding&quot;&gt;Encoding&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Encoding&quot; [18442-18463] --&gt;
&lt;h3&gt;&lt;a name=&quot;button1&quot; id=&quot;button1&quot;&gt;&amp;quot;Button&amp;quot;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Sample should be changed when user presses a button. But we should remember that user may never press a button, therefore it is nessesary to initialize array in RAM before waiting the button pressing.
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; Task_Button &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; s_cCurSample;   &lt;span class=&quot;co1&quot;&gt;// Current sample&lt;/span&gt;
&amp;nbsp;
    s_cCurSample &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
&amp;nbsp;
    CopySample&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;s_cCurSample&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;;;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Wait for key press (with debounce)&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            OS_Cond_Wait&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;pin_BUTTON&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
            OS_Delay&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;40&lt;/span&gt; ms&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;pin_BUTTON&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Chenging sample, copy sample info into RAM&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        s_cCurSample++;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;s_cCurSample &lt;span class=&quot;sy1&quot;&gt;&amp;gt;=&lt;/span&gt; MAX_SAMPLES&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; s_cCurSample &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        CopySample&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;s_cCurSample&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Wait for key release&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            OS_Cond_Wait&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;pin_BUTTON&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
            OS_Delay&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;40&lt;/span&gt; ms&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;pin_BUTTON&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&amp;nbsp;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Note that variable &lt;strong&gt;s_cCurSample&lt;/strong&gt; defined as static, as it is important to keep it&amp;#039;s value after task switching. Function CopySample just copies array from ROM into RAM:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; CopySample &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; n;
    c &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;n &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; n &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;64&lt;/span&gt;; n&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; Sample&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;n&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; SAMPLES&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;c&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;n&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;Button&quot; [18464-20233] --&gt;
&lt;h3&gt;&lt;a name=&quot;keyboard1&quot; id=&quot;keyboard1&quot;&gt;&amp;quot;Keyboard&amp;quot;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Ths task every 10 ms scans all 6 rows of keyboard matrix. In the begin of task all treshold values are zeroed. Function that reads keys in row checks these values for zero and writes to them measured ADC data minus 15% (=85%).
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;&lt;strong&gt;Note.&lt;/strong&gt; If you will use surface between finger and sensor, then treshold voltage should be about 95% of untouched sensor.&lt;/em&gt;
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; Task_Keyboard &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; n;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; s_cChanged;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Make call of ReadRow to make sure that all analog input pins are&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  configured as digital output (to discharge capasitors)&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    ReadRow&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  First time all reference values are cleared (not set)&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;n &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; n &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; KBD_COLUMNS; n&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;Tresholds&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;n&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;;;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Set bit mask for first key&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;  &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;                  &lt;span class=&quot;co1&quot;&gt;// Byte number&lt;/span&gt;
        KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;;               &lt;span class=&quot;co1&quot;&gt;// Bit mask in byte&lt;/span&gt;
        s_cChanged &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;                     &lt;span class=&quot;co1&quot;&gt;// Boolean value: =1 - keys states&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// were changed&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;n &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; n &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; KBD_ROWS; n&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;      &lt;span class=&quot;co1&quot;&gt;// Loop by all rows&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            s_cChanged |= ReadRow&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;n&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;       &lt;span class=&quot;co1&quot;&gt;// Measuring of all sensors (key) in a&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// row may take about 500 us. So&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// between row measures we switch&lt;/span&gt;
                                            &lt;span class=&quot;co1&quot;&gt;// tasks.&lt;/span&gt;
            OS_Yield&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  If keyboard state was changed, then send a message to Task_Sound&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;s_cChanged&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            OS_Msg_Send_Now&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;msg_KBD, &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;OST_MSG&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
        OS_Delay&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt; ms&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Now we will encode function that reads capacitive sensors.
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; ReadRow &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; row&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;        m, a, i, k;             &lt;span class=&quot;co1&quot;&gt;// Additional variables&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;        col;                    &lt;span class=&quot;co1&quot;&gt;// Current analog input (column)&lt;/span&gt;
    TColumn     Column;                 &lt;span class=&quot;co1&quot;&gt;// Use a variable to redice code size and&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// increaze speed.&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; s_Changes&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD_SIZE&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;// For debounce: changes since last reading&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; bit  s_bChanged;             &lt;span class=&quot;co1&quot;&gt;// ariable o be returned&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;ROWS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;row&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;pPort&lt;/span&gt; |= ROWS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;row&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;;&lt;span class=&quot;co1&quot;&gt;// Set row control output to &amp;quot;1&amp;quot;&lt;/span&gt;
&amp;nbsp;
    s_bChanged &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;                     &lt;span class=&quot;co1&quot;&gt;// First we suppose that there were not&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// any changes in keyboard state&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//******************************************************************************&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//   Loop for all columns&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//******************************************************************************&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;col &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; col  &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; KBD_COLUMNS; col&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;// Copy channel info into RAM variable to reduce code size&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        Column.&lt;span class=&quot;me1&quot;&gt;pPort&lt;/span&gt;       &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; COLUMNS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;pPort&lt;/span&gt;;
        Column.&lt;span class=&quot;me1&quot;&gt;pTris&lt;/span&gt;       &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; COLUMNS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;pTris&lt;/span&gt;;
        Column.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;       &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; COLUMNS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;;
        Column.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; COLUMNS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Select ADC channel&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        CHS0 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        CHS1 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        CHS2 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CHS0 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CHS1 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x04&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CHS2 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co2&quot;&gt;#if defined(_16F887) || defined(_16F886) || defined(_16F690)&lt;/span&gt;
        CHS3 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;cADCChannel&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x08&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CHS3 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
        &lt;span class=&quot;co2&quot;&gt;#endif&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Start measuring&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        GIE &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;                        &lt;span class=&quot;co1&quot;&gt;// Disabling interrupts while making delay&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// to charge capasitor&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;pTris&lt;/span&gt; |=  Column.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;; &lt;span class=&quot;co1&quot;&gt;// Start capasitor sensor charging by&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// set analog pin for input (high imp.)&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;m &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; m &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;; m&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; NOP&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;  &lt;span class=&quot;co1&quot;&gt;// CHARGING DELAY&lt;/span&gt;
&amp;nbsp;
        GODONE &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;                     &lt;span class=&quot;co1&quot;&gt;// Start AD conversion.&lt;/span&gt;
        GIE &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;                        &lt;span class=&quot;co1&quot;&gt;// Now we can enable interrupts&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;GODONE&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;continue&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  AD conversion is done. Now forming key states array.&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;pTris&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~Column.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;;
        &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;Column.&lt;span class=&quot;me1&quot;&gt;pPort&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~Column.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;; &lt;span class=&quot;co1&quot;&gt;// Discharge capasitor by switching analog&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// input to output &amp;quot;0&amp;quot;&lt;/span&gt;
        a &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ADRESH;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Set reference for current channel if it not set yet&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        m &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;Tresholds&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;         &lt;span class=&quot;co1&quot;&gt;// Copy element of array in vaiable to&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// reduce code size&lt;/span&gt;
        i &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;a &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; m&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; i &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;;   &lt;span class=&quot;co1&quot;&gt;// Compare with reference value. If just read&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// value is less than reference, then&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// capasitor were charged to slow. It&lt;/span&gt;
                                        &lt;span class=&quot;co1&quot;&gt;// means that key is pressed.&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;m&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;                         &lt;span class=&quot;co1&quot;&gt;// If reference is not set (is zero) then&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                               &lt;span class=&quot;co1&quot;&gt;// set it as 88% of current ADRESH value&lt;/span&gt;
            m &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;sy1&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;;
            KBD.&lt;span class=&quot;me1&quot;&gt;Tresholds&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;col&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;sy2&quot;&gt;-&lt;/span&gt; m;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Setting new keyboard state (with debounce)&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        m  &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt;  KBD.&lt;span class=&quot;me1&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;   &lt;span class=&quot;co1&quot;&gt;// To reduce code size we will work with&lt;/span&gt;
        k  &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt;  s_Changes&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;  &lt;span class=&quot;co1&quot;&gt;// copy of array's element&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;m &lt;span class=&quot;sy3&quot;&gt;^&lt;/span&gt; i&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                               &lt;span class=&quot;co1&quot;&gt;// Key state was changed:&lt;/span&gt;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;k &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;   &lt;span class=&quot;co1&quot;&gt;//   Just now:&lt;/span&gt;
                k |=  KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;//     Set change token&lt;/span&gt;
&amp;nbsp;
            &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt;                        &lt;span class=&quot;co1&quot;&gt;//   Not just now:&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                m &lt;span class=&quot;sy3&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt;  KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;//     Set new key state&lt;/span&gt;
                s_bChanged &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;         &lt;span class=&quot;co1&quot;&gt;//     Form variableto be returned&lt;/span&gt;
                k &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;//     Reset change token&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                        &lt;span class=&quot;co1&quot;&gt;// Key state remain unchanged&lt;/span&gt;
            k &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;;        &lt;span class=&quot;co1&quot;&gt;//   Reset change token&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        KBD.&lt;span class=&quot;me1&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; m;     &lt;span class=&quot;co1&quot;&gt;// Restore array's elements from&lt;/span&gt;
        s_Changes&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; k;    &lt;span class=&quot;co1&quot;&gt;// temp variables&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//   Set bit mask for next key&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            KBD.&lt;span class=&quot;me1&quot;&gt;cDataMask&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;;
            KBD.&lt;span class=&quot;me1&quot;&gt;cDataPos&lt;/span&gt;++;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;ROWS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;row&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;pPort&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~ROWS&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;row&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;cMask&lt;/span&gt;;   &lt;span class=&quot;co1&quot;&gt;// Set row control output to &amp;quot;0&amp;quot;&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; s_bChanged;
&amp;nbsp;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Let&amp;#039;s pay attention on forming delay string:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;m &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; m &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;; m&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; NOP&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/pre&gt;
&lt;p&gt;
In this case program forms pause for resistance 100K in RC-curcuit. This delay provides capasitive charge up to Vdd/2. If you suppose to use other values of resustors, it will be better (but not nessesary) to recount constant in for-cycle. E.g. for 200K this cycle should be executed 6 times.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Keyboard&quot; [20234-29503] --&gt;
&lt;h3&gt;&lt;a name=&quot;sound&quot; id=&quot;sound&quot;&gt;&amp;quot;Sound&amp;quot;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

This task will accept message from Task_Keyboard and form sound variables for syntheszer. After accepting a message, it will be copyed into internal array. Then we check all sound variables to:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; stop sound for no longer pressed keys;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; delete already played keys from list of keys (internal array);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; count number of free channels.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
After that operation we have a variable &lt;strong&gt;cFreeSounds&lt;/strong&gt; that shows how many channels are free, and list of just pressed keys. If this list is not empty and there are some free channels, than new sounds will be added.
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;TSound      S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;MAX_CHANNELS&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;    &lt;span class=&quot;co1&quot;&gt;// Sound variables&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; Task_Sound &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    OST_MSG         msg;            &lt;span class=&quot;co1&quot;&gt;// Variable to receive message&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;KBD_SIZE&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span class=&quot;co1&quot;&gt;// Array where keyboard state will be copied to&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   cMask;          &lt;span class=&quot;co1&quot;&gt;// Two temparary variables to address bits in&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   cPos;           &lt;span class=&quot;co1&quot;&gt;// array.&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   cFreeSounds;    &lt;span class=&quot;co1&quot;&gt;// How many free channels we have.&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;   i, j;           &lt;span class=&quot;co1&quot;&gt;// Temp variables&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;;;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//   Wait for changing of keybaord state. Copy keyboard state into Data&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//   array&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        OS_Msg_Wait&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;msg_KBD, msg&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;i &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; i &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; KBD_SIZE; i&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;msg&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  If key is played now, then it will be deleted from list of pressed&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  keys. At the same time we will count number of free sound channels.&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        cFreeSounds &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;i &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;; i &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; MAX_CHANNELS; i&lt;span class=&quot;sy2&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;      &lt;span class=&quot;co1&quot;&gt;// Check all channels&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;                  &lt;span class=&quot;co1&quot;&gt;// If current channel is quiet then&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                                   &lt;span class=&quot;co1&quot;&gt;// increase number of free channels.&lt;/span&gt;
                cFreeSounds++;
                &lt;span class=&quot;kw1&quot;&gt;continue&lt;/span&gt;;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
            j &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;                   &lt;span class=&quot;co1&quot;&gt;// Forming bit address according to&lt;/span&gt;
            cMask &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;j &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;               &lt;span class=&quot;co1&quot;&gt;// current sound channel&lt;/span&gt;
            cPos &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; j &lt;span class=&quot;sy1&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;;
&amp;nbsp;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;cPos&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; cMask&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;             &lt;span class=&quot;co1&quot;&gt;// If key is still pressed then delete it&lt;/span&gt;
                Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;cPos&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; ~cMask;           &lt;span class=&quot;co1&quot;&gt;// from list of pressed keys&lt;/span&gt;
            &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                cFreeSounds++;                  &lt;span class=&quot;co1&quot;&gt;// Else stop channel's sound and increase&lt;/span&gt;
                S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;                   &lt;span class=&quot;co1&quot;&gt;// free channels counter&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  Now variable cFreeSounds contain number of free channels. They can be&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//  used to play sounds for just pressed keys.&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
        cMask &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;;   &lt;span class=&quot;co1&quot;&gt;// Start searching just pressed keys&lt;/span&gt;
        cPos &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
        j &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;          &lt;span class=&quot;co1&quot;&gt;// Keys counter&lt;/span&gt;
        i &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;          &lt;span class=&quot;co1&quot;&gt;// Channels counter&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;j &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&lt;/span&gt; KBD_KEYS&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cFreeSounds&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;Data&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;cPos&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; cMask&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;     &lt;span class=&quot;co1&quot;&gt;// Is key pressed?&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                           &lt;span class=&quot;co1&quot;&gt;// Yes.&lt;/span&gt;
                &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; i++;   &lt;span class=&quot;co1&quot;&gt;// Search for free channel&lt;/span&gt;
&amp;nbsp;
                                        &lt;span class=&quot;co1&quot;&gt;// Forming sound control variable:&lt;/span&gt;
                S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; Freq&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;j&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;;       &lt;span class=&quot;co1&quot;&gt;//      Frequency&lt;/span&gt;
                S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;             &lt;span class=&quot;co1&quot;&gt;//      Phase&lt;/span&gt;
                S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; j &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;       &lt;span class=&quot;co1&quot;&gt;//      Store current key&lt;/span&gt;
                cFreeSounds--;          &lt;span class=&quot;co1&quot;&gt;//      Decrease number of free channels&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
            j++;                        &lt;span class=&quot;co1&quot;&gt;// Get next key&lt;/span&gt;
            cMask &lt;span class=&quot;sy1&quot;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
            &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;cMask&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
                cMask &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;;
                cPos++;
            &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;   &lt;span class=&quot;co1&quot;&gt;//  for(;;)&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;Sound&quot; [29504-33682] --&gt;
&lt;h3&gt;&lt;a name=&quot;synthesizer&quot; id=&quot;synthesizer&quot;&gt;Synthesizer&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

As we decided before, code for sound generation will be placed into ISR. We use interrupt on TMR2. TMR2 is already used by PWM module (PWM frequency is 78KHz). We need for interrupt occured with frequency 19.5 KHz. Therefore postscaler for TMR2 will be set to 4. 
&lt;/p&gt;

&lt;p&gt;
So, interrupt on TMR2 occures every 51.2 us. Here we will generate a sound (or PWM duty cycle).
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; interrupt isr &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt;  &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt;    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;    prs;        &lt;span class=&quot;co1&quot;&gt;// OS_Timer's prescalser&lt;/span&gt;
            &lt;span class=&quot;kw4&quot;&gt;signed&lt;/span&gt;      &lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt;     temp_dac;   &lt;span class=&quot;co1&quot;&gt;// Summa of all signals&lt;/span&gt;
            &lt;span class=&quot;kw4&quot;&gt;unsigned&lt;/span&gt;    &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;    m_cDAC;     &lt;span class=&quot;co1&quot;&gt;// Value of DAC&lt;/span&gt;
&amp;nbsp;
&amp;nbsp;
    TMR2IF &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
    temp_dac &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Forming DAC value&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    SOUND&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    temp_dac &lt;span class=&quot;sy1&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;;     &lt;span class=&quot;co1&quot;&gt;// Divide by number of channels (8)&lt;/span&gt;
&amp;nbsp;
    m_cDAC  &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;temp_dac&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x80&lt;/span&gt;;
    m_cDAC &lt;span class=&quot;sy1&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Out currect DAC value through PWM&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    CCP_bit1 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
    CCP_bit0 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;;
    &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;temp_dac &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CCP_bit1 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;
    &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;temp_dac &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; CCP_bit0 &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt; ;
    CCPR1L &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; m_cDAC;
&amp;nbsp;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Macro SOUND is:

&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;co2&quot;&gt;#define SOUND(x)                                        \&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;                                     \
        temp_dac &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; Sample&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x3F&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;; \
        &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;     \
        &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;     \
        &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;CARRY&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;&amp;amp;&lt;/span&gt;S&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;sy2&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;;            \
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;

It used for conveniens. After checking for channel activity (field &lt;strong&gt;cKey&lt;/strong&gt; != 0) we read next value from an array of sample data (according to sound frequency &lt;strong&gt;F&lt;/strong&gt; and current phase &lt;strong&gt;f&lt;/strong&gt;) and add it to common sum &lt;strong&gt;temp_adc&lt;/strong&gt;. After that we recount phase of sound.
&lt;/p&gt;

&lt;p&gt;
Now, we just need to add work with system timer. Our system tick will be 10 ms (every 200th interrupt):

&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Call system timer once per 200 periods (interval = 10 ms)&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;sy3&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;sy2&quot;&gt;--&lt;/span&gt;prs&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
        OS_Timer&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;     &lt;span class=&quot;co1&quot;&gt;// System timer&lt;/span&gt;
        prs &lt;span class=&quot;sy1&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;200&lt;/span&gt;;
    &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;Synthesizer&quot; [33683-36264] --&gt;
&lt;h3&gt;&lt;a name=&quot;main&quot; id=&quot;main&quot;&gt;main()&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Here we will initialize PIC periphery and operating system, create tasks and run shceduler. All tasks will have identical priority (0 - highest).
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; main &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Init PIC periphery&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    Init&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  OSA initialisation&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    OS_Init&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Create all task with identical priority&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    OS_Task_Create&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;, Task_Sound&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    OS_Task_Create&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;, Task_Button&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    OS_Task_Create&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu19&quot;&gt;0&lt;/span&gt;, Task_Keyboard&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//  Enable interrupts and run system&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
    OS_EI&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
    OS_Run&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;main()&quot; [36265-37481] --&gt;
&lt;h3&gt;&lt;a name=&quot;osa_configuration&quot; id=&quot;osa_configuration&quot;&gt;OSA configuration&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

To configure our project we will use OSAcfg_Tool wizard. Run OSAcfg_Tool.exe and follow steps below:
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;select_project_folder&quot; id=&quot;select_project_folder&quot;&gt;1. Select project folder&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

Press button &lt;strong&gt;Browse&lt;/strong&gt; in top-right corner of dialog window. Select folder where project located in (&amp;quot;C:\TEST\PICKIT2\PIANO&amp;quot;). Press &amp;quot;OK&amp;quot;. If config file OSAcfg.h does not exist yet, then program will ask you &amp;quot;do you want to create this file?&amp;quot;. Answer &amp;quot;Yes&amp;quot;.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;set_project_name&quot; id=&quot;set_project_name&quot;&gt;2. Set project name&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

In field &lt;strong&gt;Name&lt;/strong&gt; you can enter the name for your project. It is not nessesary. Name is used to avoid confusing in future. Enter name &amp;quot;SENSOR PIANO&amp;quot;.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;select_platform&quot; id=&quot;select_platform&quot;&gt;3. Select platform&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

This item is not nessesary too. It allows to view in real time how march RAM OSA needs with current configuration. Select platform: 14-bit (PIC12, PIC16)(ht-picc). Now, on any configuration change, program will show us number of used bytes in each RAM-bank in &lt;strong&gt;RAM statistic&lt;/strong&gt; sector.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;configure_project&quot; id=&quot;configure_project&quot;&gt;4. Configure project&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

All tasks have identical priority. Therefore we can check &lt;strong&gt;Disable priority&lt;/strong&gt;. This will reduce code size and increase scheduler&amp;#039;s speed.
&lt;/p&gt;

&lt;p&gt;
Next step is setting number of tasks that will be active at same time. Three in our case. 
&lt;/p&gt;

&lt;p&gt;
Our program uses many variables. Thus it is reasonable to allocate all system variabls in higher RAM-bank. Select &lt;strong&gt;bank2&lt;/strong&gt; in combo &lt;strong&gt;OSA variables bank&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Now we tell to system that we need task timers (as we use &lt;acronym title=&quot;Operating System&quot;&gt;OS&lt;/acronym&gt;_Delay in our porgram). Check &lt;strong&gt;Task timers&lt;/strong&gt;. Due to we do not use delays longer than 256 system ticks (2.5 sec), it is recommended to set task timer type to char. It will increase speed of &lt;acronym title=&quot;Operating System&quot;&gt;OS&lt;/acronym&gt;_Timer work.
&lt;/p&gt;

&lt;p&gt;
And last: check &lt;strong&gt;Use in-line &lt;acronym title=&quot;Operating System&quot;&gt;OS&lt;/acronym&gt;_Timer()&lt;/strong&gt; to increase speed of &lt;acronym title=&quot;Operating System&quot;&gt;OS&lt;/acronym&gt;_Timer() execution.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;save_and_exit&quot; id=&quot;save_and_exit&quot;&gt;5. Save and exit&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

Press &lt;strong&gt;Save&lt;/strong&gt; button to save edited configuration file. Than press &amp;quot;Exit&amp;quot; to exit program. Now you can look into created file OSAcfg.h:
&lt;/p&gt;
&lt;pre class=&quot;cpp code cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;/******************************************************************************/&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// This file was generated by OSAcfg_Tool utility.&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// Do not modify it to prevent data loss on next editing.&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// PROJECT NAME: SENSOR PIANO&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// PLATFORM:     HT-PICC 14-bit&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;coMULTI&quot;&gt;/******************************************************************************/&lt;/span&gt;
&amp;nbsp;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#ifndef _OSACFG_H&lt;/span&gt;
&lt;span class=&quot;co2&quot;&gt;#define _OSACFG_H&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// SYSTEM&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#define OS_TASKS               3  // Number of tasks that can be active at one time&lt;/span&gt;
&lt;span class=&quot;co2&quot;&gt;#define OS_DISABLE_PRIORITY       //&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// ENABLE CONSTANTS&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#define OS_ENABLE_TTIMERS          // Enable task timers&lt;/span&gt;
&lt;span class=&quot;co2&quot;&gt;#define OS_USE_INLINE_TIMER        // Make OS_Timer service as in-line function&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// BANKS&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#define OS_BANK_OS             2  // RAM bank to allocate all system variables&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// TYPES&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;//------------------------------------------------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#define OS_TTIMER_SIZE         1&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;co2&quot;&gt;#endif&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;!-- SECTION &quot;OSA configuration&quot; [37482-40825] --&gt;
&lt;h2&gt;&lt;a name=&quot;programming&quot; id=&quot;programming&quot;&gt;Programming&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Programming&quot; [40826-40853] --&gt;
&lt;h3&gt;&lt;a name=&quot;building_a_project&quot; id=&quot;building_a_project&quot;&gt;Building a project&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

To build uor project we need next:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Installed &lt;a href=&quot;http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=1406&amp;amp;dDocName=en019469&amp;amp;part=SW007002&quot; class=&quot;urlextern&quot; title=&quot;http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=1406&amp;amp;dDocName=en019469&amp;amp;part=SW007002&quot;  rel=&quot;nofollow&quot;&gt;MPLAB IDE&lt;/a&gt;;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Installed &lt;a href=&quot;http://www.htsoft.com/microchip/products/compilers/picccompiler.php&quot; class=&quot;urlextern&quot; title=&quot;http://www.htsoft.com/microchip/products/compilers/picccompiler.php&quot;  rel=&quot;nofollow&quot;&gt;HI-TECH PICC STD compiler&lt;/a&gt; (PRO version will not work).&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

Now:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Download &lt;a href=&quot;http://wiki.pic24.ru/lib/exe/fetch.php/osa/history/osa_90406.zip&quot; class=&quot;urlextern&quot; title=&quot;http://wiki.pic24.ru/lib/exe/fetch.php/osa/history/osa_90406.zip&quot;  rel=&quot;nofollow&quot;&gt;RTOS OSA files&lt;/a&gt; and unpack it into &amp;quot;c:&amp;quot; (folder C:\OSA will be created);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Unpack &lt;strong&gt;&lt;a href=&quot;http://wiki.pic24.ru/lib/exe/fetch.php/en/osa/articles/piano_en.rar&quot; class=&quot;urlextern&quot; title=&quot;http://wiki.pic24.ru/lib/exe/fetch.php/en/osa/articles/piano_en.rar&quot;  rel=&quot;nofollow&quot;&gt;piano_en.rar&lt;/a&gt;&lt;/strong&gt; into &amp;quot;C:\TEST\PICKIT2&amp;quot; (folder &amp;quot;PIANO&amp;quot; will be created);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Open project for your controller with MPLAB IDE (there are four projects for controllers: 16F88, 16F690, 16F886, 16F887).&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

&lt;strong&gt;Note:&lt;/strong&gt;&lt;em&gt; if you want to install project into folder other then &amp;quot;C:\TEST\PICKIT2\PIANO&amp;quot;, then you need to change include path to it through &lt;strong&gt;Project\Build options…\Project&lt;/strong&gt; menu in &lt;strong&gt;Directories&lt;/strong&gt; tab.&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Build your project with &lt;strong&gt;Ctrl+F10&lt;/strong&gt;.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Building a project&quot; [40854-41890] --&gt;
&lt;h3&gt;&lt;a name=&quot;programming_with_pickit2&quot; id=&quot;programming_with_pickit2&quot;&gt;Programming with PicKit2&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Here you should to do next: 
&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; connect programmer;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; select &amp;quot;PicKit2&amp;quot; through &amp;quot;Programmer\Select programmer&amp;quot; menu;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; select &amp;lt;3-State on &amp;lt;Release from Reset&amp;gt; in &amp;quot;Programmer→Settings&amp;quot;;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; start programming &amp;quot;Programmer\Program&amp;quot;;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; make &amp;quot;Programmer\Release from reset&amp;quot;.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

That&amp;#039;s it!
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Programming with PicKit2&quot; [41891-42215] --&gt;
&lt;h2&gt;&lt;a name=&quot;schematic&quot; id=&quot;schematic&quot;&gt;Schematic&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

Here I&amp;#039;ll describe pin scheme to connect keyboard matrix to different PICs: 16F690, 16F88, 16F886, 16F887.
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;&lt;strong&gt;Important notice:&lt;/strong&gt; pins where columns will be connected to should no contain any external components except keyboard matrix. Elsewere these components will add their capasitance and resistance into scheme.&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_scheme_matrix.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_scheme_matrix.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_scheme_matrix.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Analog inputs have additive ESD protection according to Microchip&amp;#039;s document:&lt;a href=&quot;http://ww1.microchip.com/downloads/en/AppNotes/01102a.pdf&quot; class=&quot;urlextern&quot; title=&quot;http://ww1.microchip.com/downloads/en/AppNotes/01102a.pdf&quot;  rel=&quot;nofollow&quot;&gt;Layout and Physical Design Guidelines for Capacitive Sensing (PDF)&lt;/a&gt;. 
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_scheme690.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_scheme690.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_scheme690.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br/&gt;
 
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_scheme88.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_scheme88.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_scheme88.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br/&gt;
 
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_scheme886.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_scheme886.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_scheme886.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br/&gt;
 
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/en/osa/articles/pk2_osa_piano_scheme887.png?id=en%3Aosa%3Aarticles%3Apk2_osa_piano&quot; class=&quot;media&quot; title=&quot;en:osa:articles:pk2_osa_piano_scheme887.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/en/osa/articles/pk2_osa_piano_scheme887.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br/&gt;
 
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Schematic&quot; [42216-42950] --&gt;
&lt;h2&gt;&lt;a name=&quot;summary&quot; id=&quot;summary&quot;&gt;Summary&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

So, this article described two interesting things for beginners: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; keys reading. Not usual keys, but touch keys. They can work in damp and in dust;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; sound generation (not usual beep, but polyphonic sound).&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  
And I am sure that you will use these techniques in you projects in future to make your devices more interesting and life.
&lt;/p&gt;

&lt;p&gt;
Why we used RTOS? 
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; RTOS provided us with multi-tasking. And we even didn&amp;#039;t think about how to run all our tasks at the same time;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; We were able to break our program into simple tasks. Any of these tasks my be modified as you wish very easy;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; All our tasks are independed. This allows to use them in other applications.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

What can we do now? Our program turned out to be quite flexible in adjusting:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Do you wish to connect keyboard to other pins? Correct &lt;strong&gt;ROWS&lt;/strong&gt; and &lt;strong&gt;COLUMNS&lt;/strong&gt; arrays in file &lt;strong&gt;const.h&lt;/strong&gt; and enjoy;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Do you want more keys in keyboard? Redefine &lt;strong&gt;KBD_ROWS&lt;/strong&gt; and &lt;strong&gt;KBD_COLUMNS&lt;/strong&gt; constants and add new pins into &lt;strong&gt;ROWS&lt;/strong&gt; and &lt;strong&gt;COLUMNS&lt;/strong&gt; arrays;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Do you want more channels? Increase &lt;strong&gt;MAX_CHANNELS&lt;/strong&gt; constant and decrease sampling rate;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; Do you want more musical instruments? Add data into &lt;strong&gt;SAMPLES&lt;/strong&gt; array in file sinus.c.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; ect. &lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
You are limitted by your imagination only!
&lt;/p&gt;

&lt;p&gt;
Good luck!
&lt;/p&gt;

&lt;p&gt;
&lt;br/&gt;
 
&lt;br/&gt;
 
&lt;br/&gt;
 
&lt;/p&gt;

&lt;p&gt;
Victor Timofeev, 2009, april&lt;br/&gt;
 
&lt;a href=&quot;mailto:&amp;#x6f;&amp;#x73;&amp;#x61;&amp;#x40;&amp;#x70;&amp;#x69;&amp;#x63;&amp;#x32;&amp;#x34;&amp;#x2e;&amp;#x72;&amp;#x75;&quot; class=&quot;mail JSnocheck&quot; title=&quot;&amp;#x6f;&amp;#x73;&amp;#x61;&amp;#x40;&amp;#x70;&amp;#x69;&amp;#x63;&amp;#x32;&amp;#x34;&amp;#x2e;&amp;#x72;&amp;#x75;&quot;&gt;osa@pic24.ru&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Summary&quot; [42951-] --&gt;</description>
    </item>
    <item rdf:about="http://www.pic24.ru/doku.php/en/osa/articles/vga_game?rev=1262545739">
        <dc:format>text/html</dc:format>
        <dc:date>2010-01-03T22:08:59+03:00</dc:date>
        <title>Video game with PIC18</title>
        <link>http://www.pic24.ru/doku.php/en/osa/articles/vga_game?rev=1262545739</link>
        <description>


&lt;h1&gt;&lt;a name=&quot;video_game_with_pic18&quot; id=&quot;video_game_with_pic18&quot;&gt;Video game with PIC18&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Video game with PIC18&quot; [1-37] --&gt;
&lt;h2&gt;&lt;a name=&quot;intro&quot; id=&quot;intro&quot;&gt;Intro&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

PIC18 is not quite effective controller to drive VGA monitor, but they are able to be implemented for these purposes. This example shows how to use PIC18F2550 to build video game. In 2004 I developed &lt;strong&gt;&lt;a href=&quot;http://www.pic24.ru/doku.php/osa/articles/vga_terminal&quot; class=&quot;wikilink1&quot; title=&quot;osa:articles:vga_terminal&quot;&gt;VGA-terminal&lt;/a&gt;&lt;/strong&gt;, where I used PIC18 to produce VGA control signals to form text data on the screen. When I was a boy (in early 80-th) I had a ZX Spectrum. My favorite game was a Bulder Dash by &lt;a href=&quot;http://www.firststarsoftware.com&quot; class=&quot;urlextern&quot; title=&quot;http://www.firststarsoftware.com&quot;  rel=&quot;nofollow&quot;&gt;First Star Software&lt;/a&gt;. Now I tried to encode this game woth PIC18 controller. Here are source code, video and description of my works.
&lt;/p&gt;

&lt;p&gt;
Source codes: &lt;a href=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_game.rar&quot; class=&quot;media mediafile mf_rar&quot; title=&quot;osa:articles:vga_game.rar&quot;&gt;vga_game.rar&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
All modules in this program were written in C (HT-PICC18), except interrupt service routine - it was fully written in assembler. Program controlled by RTOS OSA.
&lt;/p&gt;

&lt;p&gt;
Program specification:
&lt;/p&gt;
&lt;table class = &quot;fpl&quot;&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Controller&lt;/strong&gt; 		&lt;/td&gt;
		&lt;td&gt;
PIC18F2550		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Fosc&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
48 &lt;acronym title=&quot;Megahertz&quot;&gt;MHz&lt;/acronym&gt; (12 MIPS)		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;RTOS&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
OSA		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;VGA&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
256x200 pixels, 15 colors		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Polyphony&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
5 voices (4 for music, 1 for game effects). Sample rate = 15 KHz		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Game field&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
40x20 objects		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Viewable field size&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
16x12 objects		&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Intro&quot; [38-1182] --&gt;
&lt;h2&gt;&lt;a name=&quot;video_34_mb&quot; id=&quot;video_34_mb&quot;&gt;Video (34 Mb)&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

Here is a small video. The quality is not very well since I used low-cost web-camera. Sound was recorded through line-in.
&lt;/p&gt;

&lt;p&gt;
&lt;div align=center&gt;
&lt;object width=&quot;640&quot; height=&quot;480&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/PZjuyCuH7Ac&amp;hl=en&amp;fs=1&amp;rel=0&quot;&gt;&lt;/param&gt;
&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;

&lt;embed src=&quot;http://www.youtube.com/v/PZjuyCuH7Ac&amp;hl=en&amp;fs=1&amp;rel=0&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; width=&quot;640&quot; height=&quot;480&quot;&gt;&lt;/embed&gt;

&lt;/object&gt;
&lt;/div&gt;
&lt;br/&gt;
 
&lt;br/&gt;
 
Unfortunately I could not to record video in better way. In fact, the picture is more clearly:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_game_big_plan.jpg?id=en%3Aosa%3Aarticles%3Avga_game&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_game_big_plan.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_game_big_plan.jpg&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Video (34 Mb)&quot; [1183-1867] --&gt;
&lt;h2&gt;&lt;a name=&quot;description&quot; id=&quot;description&quot;&gt;Description&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Description&quot; [1868-1892] --&gt;
&lt;h3&gt;&lt;a name=&quot;scheme&quot; id=&quot;scheme&quot;&gt;Scheme&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

The principal scheme it rather simple:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_game_scheme.png?id=en%3Aosa%3Aarticles%3Avga_game&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_game_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_game_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Logically, scheme can be splitted into four parts:
&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; microcontroller - device&amp;#039;s heart;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; 3 resistors and 6 diodes to form RGB-signals;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; low noize filter to produce sound;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; 5 buttons with pull-up resistors.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

How to form image on VGA-monitor is described &lt;a href=&quot;http://www.pic24.ru/doku.php/osa/articles/vga_terminal#view_generating&quot; class=&quot;wikilink1&quot; title=&quot;osa:articles:vga_terminal&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Here is device&amp;#039;s photo:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_boulder_dash_device.jpg?id=en%3Aosa%3Aarticles%3Avga_game&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_boulder_dash_device.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_boulder_dash_device.jpg&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Scheme&quot; [1893-2379] --&gt;
&lt;h3&gt;&lt;a name=&quot;controller_s_resources&quot; id=&quot;controller_s_resources&quot;&gt;Controller&amp;#039;s resources&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

As you can see, controller should to do many jobs simultaneously: sync signals for VGA generating, RGB-signals generating, multyvoice sound generating. All these jobs should be synchronized to within a cycle, otherwise the picture on the monitor will shake. Besides, the game should work in real-time: buttons reading, animation, objects moving, music playing, soung effects and ect.
&lt;/p&gt;

&lt;p&gt;
I decided to put all time critical processes into interrupt service routine, and all other to put into &lt;acronym title=&quot;Operating System&quot;&gt;OS&lt;/acronym&gt; tasks functions.
&lt;/p&gt;

&lt;p&gt;
These tasks are placed into ISR:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; VGA sync pulses generating;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; RGB-singals generating;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; sound sinthesizer;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; button read with debounce.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

Other tasks are placed in remaining program part:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; making animation;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; game rules;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; music and sound effects forming.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Controller's resources&quot; [2380-3196] --&gt;
&lt;h1&gt;&lt;a name=&quot;unfinished&quot; id=&quot;unfinished&quot;&gt;(UNFINISHED)&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;p&gt;
(see &lt;strong&gt;&lt;a href=&quot;http://www.pic24.ru/doku.php/osa/articles/vga_game&quot; class=&quot;urlextern&quot; title=&quot;http://www.pic24.ru/doku.php/osa/articles/vga_game&quot;  rel=&quot;nofollow&quot;&gt;russian text&lt;/a&gt;&lt;/strong&gt;)

&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;(UNFINISHED)&quot; [3197-] --&gt;</description>
    </item>
    <item rdf:about="http://www.pic24.ru/doku.php/en/osa/articles/vga_terminal?rev=1316766129">
        <dc:format>text/html</dc:format>
        <dc:date>2011-09-23T12:22:09+03:00</dc:date>
        <title>VGA-terminal with PIC18</title>
        <link>http://www.pic24.ru/doku.php/en/osa/articles/vga_terminal?rev=1316766129</link>
        <description>


&lt;h1&gt;&lt;a name=&quot;vga-terminal_with_pic18&quot; id=&quot;vga-terminal_with_pic18&quot;&gt;VGA-terminal with PIC18&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;p&gt;

This article tells how to output data to VGA monitor using controller PIC18. This controller is not quite well for tasks like this, but this example shows that it isn&amp;#039;t impossible. This program was written in 2004, and it is introduced here just for describe principles of &lt;a href=&quot;http://www.pic24.ru/doku.php/osa/articles/vga_game&quot; class=&quot;wikilink1&quot; title=&quot;osa:articles:vga_game&quot;&gt;&amp;quot;VGA game with PIC18&amp;quot;&lt;/a&gt; project.
&lt;/p&gt;

&lt;p&gt;
Source code is here: &lt;a href=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/terminal.rar&quot; class=&quot;media mediafile mf_rar&quot; title=&quot;osa:articles:terminal.rar&quot;&gt;terminal.rar&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Specification:
&lt;/p&gt;
&lt;table class = &quot;fpl&quot;&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Text screen resolution&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
30x30 chars		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Graphics resolution&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
240x480 pixels		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Char size&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
8x16 pixels		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Colors&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
15		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Cursor emulating&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
Yes. 		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Char set&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
English, Russian		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;Interface&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
SPI, up to 250 kbits per second		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
&lt;strong&gt;&lt;/strong&gt;		&lt;/td&gt;
		&lt;td&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;

There are two limitations:
&lt;/p&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; background color is always black;&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; one symbol can be drown with one colour only.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

Here is demo mode generated screen. (Ptogram was written in 2004, and demo-screen function was added just now for demonstration purpose):
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_trm_demo_screen.jpg?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_trm_demo_screen.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_trm_demo_screen.jpg?w=350&quot; class=&quot;media&quot; alt=&quot;&quot; width=&quot;350&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_trm_large_plan.jpg?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_trm_large_plan.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_trm_large_plan.jpg?w=350&quot; class=&quot;media&quot; alt=&quot;&quot; width=&quot;350&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;VGA-terminal with PIC18&quot; [1-1076] --&gt;
&lt;h2&gt;&lt;a name=&quot;vga_colntrol&quot; id=&quot;vga_colntrol&quot;&gt;VGA colntrol&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;VGA colntrol&quot; [1077-1101] --&gt;
&lt;h3&gt;&lt;a name=&quot;some_theory&quot; id=&quot;some_theory&quot;&gt;Some theory&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

VGA monitor is controlled by 5 wires: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; 2 digital wires (horisontal and vertical syncho pulses);&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; 3 analog wires (reg, green and blue levels).&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

Syncronization wires used to tell to monitor when frame started and how march frames per second. Analog wires used to specify color of every pixel on the screen. The higher voltage on wire brings the brighter color. By combinating different voltage levels on three RGB wires we can gen different colors (e.g. when generating simmilar levels for red and green wires and zero level for blue wire, we will get yellow color).
&lt;/p&gt;

&lt;p&gt;
The picture on the sreen is drawed line by line from the top to the bottom. Each line drown left to right. When line fully drown, horisontal synchronization pulse will be generated (HSYNC) to tell to monitor that next part of information should be drown at next line. When all lines are drown, verlical sinchronization pulse (VSYNC) will be generated to tell to monitor that frame is over and next information should be outputed from the top of the screen.
&lt;/p&gt;

&lt;p&gt;
Frame rate must be greater than 60 Hz to prevent blinking. In standart VGA-mode each frame consist of 525 lines. 480 of them contain picture, and other contain top and bottom borders and blank lines for vertical sinchro (they have not color information). Each line is splitted at several parts: video information, left and right borders, horisontal blanking pulse.
&lt;/p&gt;

&lt;p&gt;
The lenght of line = 1s /60 frames / 525 lines = 31.75 us.
&lt;/p&gt;

&lt;p&gt;
Here is a picture dscribing data transfer to VGA:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_sync.png?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_sync.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_sync.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Some theory&quot; [1102-2665] --&gt;
&lt;h3&gt;&lt;a name=&quot;picture_generating&quot; id=&quot;picture_generating&quot;&gt;Picture generating&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

(not finished, see page in russian)
&lt;/p&gt;

&lt;/div&gt;

&lt;h4&gt;&lt;a name=&quot;synchro_pulses&quot; id=&quot;synchro_pulses&quot;&gt;Synchro pulses&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;

(not finished, see page in russian)
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Picture generating&quot; [2666-2793] --&gt;
&lt;h3&gt;&lt;a name=&quot;scheme&quot; id=&quot;scheme&quot;&gt;Scheme&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_terminal_scheme.png?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_terminal_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_terminal_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Scheme&quot; [2794-2856] --&gt;
&lt;h3&gt;&lt;a name=&quot;test_application&quot; id=&quot;test_application&quot;&gt;Test application&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;

Here is a small test application for PIC16F88
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/terminal_test.rar&quot; class=&quot;media mediafile mf_rar&quot; title=&quot;osa:articles:terminal_test.rar&quot;&gt;Source code&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_test_terminal_scheme.png?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_test_terminal_scheme.png&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_test_terminal_scheme.png&quot; class=&quot;media&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
This aplication draws this picture:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.pic24.ru/lib/exe/detail.php/osa/articles/vga_trm_test_screen.jpg?id=en%3Aosa%3Aarticles%3Avga_terminal&quot; class=&quot;media&quot; title=&quot;osa:articles:vga_trm_test_screen.jpg&quot;&gt;&lt;img src=&quot;http://www.pic24.ru/lib/exe/fetch.php/osa/articles/vga_trm_test_screen.jpg?w=400&quot; class=&quot;media&quot; alt=&quot;&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Test application&quot; [2857-] --&gt;</description>
    </item>
</rdf:RDF>
