tag:blogger.com,1999:blog-73345990244704928522024-03-04T20:22:21.881-08:00M-SYS MVWorking with Cortex-M3Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-7334599024470492852.post-19366171442532278862012-01-08T13:25:00.001-08:002012-01-08T13:26:39.531-08:00Frequency counter using LPC17xx<div dir="ltr" style="text-align: left;" trbidi="on">I got a couple of requests for the tutorial of making a frequency counter using LPC17xx. So I am providing the code and explanation of making a frequency counter in this post.<br />
<br />
<a name='more'></a>The basic idea of making a frequency counter is to count the number of cycles of the input in one second. We can keep one counter that keeps counting the rising/falling edges of the input signal. Then we can read the value of this counter once in a second and then clear it. The value we read from the counter is nothin but the frequency of the input signal.<br />
<br />
<span style="font-family: inherit;">1. Initialization of the counter</span><span style="font-family: inherit;"><br />
</span><br />
<span style="font-family: "Courier New", "Courier", monospace;">LPC_SC->PCONP |= 1 << 2; //Power up TimerCounter1<br />
<br />
LPC_TIM1->TCR |= 1 << 0; // Counter mode<br />
LPC_TIM1->CTCR |= 2; // Count on falling edges<br />
LPC_TIM1->CTCR |= 1 << 2; // CAP1.1 is the input pin for which the input signal needs to be connected.</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
LPC_PINCON->PINSEL3 |= 3 << 6; // Make P1.19 as CAP1.1<br />
<br />
LPC_TIM1->TCR |= 1 << 1; // Reset the counter<br />
LPC_TIM1->TCR |= 1 << 0; // Start counter</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
2. Initialization of the timer which generates interrupt once in a second<br />
<span style="font-family: "Courier New", "Courier", monospace;">LPC_SC->PCONP |= 1 << 1; //Power up Timer0<br />
LPC_SC->PCLKSEL0 |= 3 << 2; // Clock for timer = CCLK/8<br />
<br />
LPC_TIM0->MR0 = 12499999; // Assuming that clk freq = 100 MHz, this value is calculated to generate an interrupt once in a second.</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
LPC_TIM0->MCR |= 1 << 0; // Interrupt on Match0 compare<br />
LPC_TIM0->TCR |= 1 << 1; // Reset Timer0<br />
<br />
NVIC_EnableIRQ(TIMER0_IRQn); // Enable timer interrupt<br />
<br />
LPC_TIM0->TCR |= 1 << 0; // Start timer</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
<span style="font-family: inherit;">3. Timer interrupt routine</span><span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
<span style="font-family: inherit;">In this routine we need to read the value of the counter if the interrupt was generated by MR0 and then we need to clear the counter.</span><span style="font-family: inherit;"><br />
</span><br />
<span style="font-family: "Courier New", "Courier", monospace;">inputFreq = LPC_TIM1->TC; // Read the counter value<br />
LPC_TIM1->TCR |= 1 << 1; // Reset the counter</span><span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
The input frequency value is now stored in the variable inputFreq. The main.cpp file for this program can be found <a href="http://cortex-m3-tutorials.googlecode.com/files/frequency_counter.cpp">here</a>.<br />
<br />
WARNING: This code needs to be integrated with the CMSIS LPC17xx code base and needs to be compiled. I have not tested this code on hardware.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com4tag:blogger.com,1999:blog-7334599024470492852.post-85481642311345276962011-10-13T18:26:00.000-07:002011-10-13T20:41:51.523-07:00MIDI synthesizer on mbed<div dir="ltr" style="text-align: left;" trbidi="on">Finally my long term desire to make a MIDI synthesizer using touchpad was satisfied. When I first thought of making a MIDI synthesizer two years ago, I was planning to do it using an AVR microcontroller but the implementation of it was procrastinated till now.<br />
<br />
<a name='more'></a><br />
<br />
This MIDI synthesizer is implemented on mbed by using two touchpads. Each touchpad has 12 pads which correspond to 12 different notes in a single octave. So with two touchpads, we have 2 octaves that can be used to compose the song simultaneously. More touchpads can be interfaced to increase the number of octaves available simultaneously.<br />
<br />
The basic idea is that mbed captures touch events (pad press and release events) from both the touchpads, notes the difference between the times of different events by using timer and sends a command to the PC via virtual serial port. We have written a C# windows forms application which captures the commands sent by the mbed via virtual serial port and then calculates MIDI delta time, creates the MIDI event and writes it to a file. The application also playbacks the notes when the corresponding pad on the touchpad is hit.<br />
<br />
We have also put an LCD which shows the octave number of the touchpads. LCD also displays the FFT of the notes being played. We have provided four pushbuttons to increase or decrease the octave numbers of the touchpads.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge1z900GzSIxdbYTcQvmELt7pnC2n_ylAL3QjfCTZqr-pZM1VMvmnjkI4KVFPJt1_lAifQ_IWGRUB8fThtoe6FOPY31ighyphenhyphen0G31e-nV9N-O9sJq_8ZJgUgT0Gj4kF8QwAJdZfgJbRFLIJY/s1600/Untitled.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge1z900GzSIxdbYTcQvmELt7pnC2n_ylAL3QjfCTZqr-pZM1VMvmnjkI4KVFPJt1_lAifQ_IWGRUB8fThtoe6FOPY31ighyphenhyphen0G31e-nV9N-O9sJq_8ZJgUgT0Gj4kF8QwAJdZfgJbRFLIJY/s320/Untitled.jpg" width="300" /> </a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div align="left" class="separator" style="clear: both; text-align: center;"><br />
</div><div align="left" class="separator" style="clear: both; text-align: center;"><br />
</div>Here is a video of our project.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/jQn6Ps4o8vc?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<br />
<a href="http://mbed.org/users/thejasvi3/notebook/midi-sythesizer/">Here</a> is the mbed notebook of this project. Visit it for more information, <a href="http://mbed.org/users/thejasvi3/programs/MIDI_Synthesizer/lyypvl">project code</a> and <a href="http://mbed.org/media/uploads/thejasvi3/midi_synthesizer_application.zip">C# Windows forms application</a>.<br />
<br />
<b>Scope for improvement</b><br />
<ul style="text-align: left;"><li><b> </b>Due to the non-availability of the sample note files of different instruments, the current playback in our project is just a sine wave of the given note frequencies. If anyone gets the sample files they can implement real playback feature. </li>
</ul><ul style="text-align: left;"><li>More touchpads can be interfaced to give the user flexibility of composing with notes at different octaves without using pushbuttons. </li>
</ul><ul style="text-align: left;"><li>By using MIDI waveform generation techniques, the playback can be implemented on the mbed itself.</li>
</ul><br />
Share your ideas for improvement. If anyone has sample note files of different instruments please share it with me. Thank you.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com0tag:blogger.com,1999:blog-7334599024470492852.post-88308515358223725322011-10-13T13:08:00.000-07:002011-10-13T13:16:04.237-07:00Working with mbed<div dir="ltr" style="text-align: left;" trbidi="on">After one year of working with the NGX blueboard, I finally got a chance to fool around with mbed. Till now I was wondering as to what makes mbed so popular. I came to know the reason after working with it.<br />
<br />
<a name='more'></a>The first thing I noticed is that mbed has a USB bootloader that comes along with the board. So you need not search for the USB bootloader on the internet and burn it to your microcontroller. Secondly, the board is lot more compact than the NGX blueboard. Thirdly, the cloud compiler is nice to work with. Now you will have your files wherever you go. Finally, a lot of people have already worked with mbed and have developed and shared the libraries to do different things. So it makes your work a lot easier.<br />
<br />
One thing I would like to have for mbed is advanced compiler options which will allow me to tweak my code as I wish and also which allows me to choose the optimization level. In some program, for some reason, I might need to do something (loops without body or something like that) that does not affect the end result of the program. In such cases I would not want the compiler to ignore that code. So I would like to have control over the compiler optimization level. Well you can change the compiler optimization by using pragmas. But what about other compiler settings? Do I need to learn the commands for all the settings? Well the compiler thing wont be that big a problem if you use some other offline compiler that you like.<br />
<br />
In the application development point of view one can very easily develop complex applications within days by using mbed as there is no need to do all the peripheral initializations by hand and also due to the abundance of libraries to do all sorts of common things. But I would recommend beginners not to use the classes and libraries provided by mbed. Try to do all things on your own. That way you will learn about the microcontroller in deep and also it will help you very much while debugging complex codes or silly mistakes. If you use a library, try to understand what the author is doing in the library and use it.<br />
<br />
If you want to share your experience of working with mbed or NGX blueboard or in general ARM this is the place to share.<br />
<br />
Anyway mbed or NGX blueboard does not matter. LPC17xx is FUN to work with.<br />
<br />
SPOILER: The description and demo of a new mbed project done by me and my colleague will be posted shortly.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com4tag:blogger.com,1999:blog-7334599024470492852.post-28363563775555270782011-05-25T23:28:00.000-07:002011-10-13T13:15:31.395-07:00MCPWM in LPC17xx<div dir="ltr" style="text-align: left;" trbidi="on">Motor Control PWM can be used to control AC and DC motors. It can also be used for many other purposes which require timing, counting, comparing or capturing. The MCPWM is used for generating audio signals in the 2d game console as the general PWM is used for color generation. And I will be discussing as to how it works and how to initialize it.<br />
<a name='more'></a><br />
There are 3 MCPWM channels in LPC1768. Each channel contains its own 32-bit timer, 32-bit Limit register, 32-bit Match register, 10-bit deadtime register and 32-bit capture register. And there will be two output pins for each channel named A and B. The A and B outputs will be complementary to each other. Here the Limit register sets the TOP value of the timer. Hence the timer counts from 0 to the Limit value. So one can set the PWM frequency by choosing a correct prescaler (clock frequency divider) and the limit value.<br />
<br />
There are two modes, one is edge aligned and the other is center aligned mode. In edge aligned mode, the timer will count upwards from 0 to limit and goes back to 0 and the output toggles when the timer value matches with the match register or the limit register. In center aligned mode, the timer will count upwards from 0 to limit and then counts downward from limit to 0 and the output toggles only when the timer value matches the match register value. If you are looking for a phase correct mode, then you should use center aligned mode.<br />
<br />
You can even set the passive polarity of the output. If you select passive polarity state as LOW, then the MCPWM output signal will be LOW until the timer value matches the match register value and will be HIGH from the time when match occurs till the timer value matches the limit register value. If the polarity state is selected as HIGH, then the reverse will happen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW7HzBCvXBashjhDfrr2uyt9JmWybm3eTKAeUVergCxEjrHpbihaF_Q9rYWY-0l0c4mLFK0pXFGFKWwAd-QuFh8WRGcAIQWy30SVNI0nS4ScWu2lHfT2g3hrRX1bBXrPam3ZgF9OJAYeRM/s1600/img1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW7HzBCvXBashjhDfrr2uyt9JmWybm3eTKAeUVergCxEjrHpbihaF_Q9rYWY-0l0c4mLFK0pXFGFKWwAd-QuFh8WRGcAIQWy30SVNI0nS4ScWu2lHfT2g3hrRX1bBXrPam3ZgF9OJAYeRM/s400/img1.png" width="400" /></a></div><br />
<div style="text-align: center;"> Figure 1: Waveform indicating the output of MCPWM channel 0 with polarity as 0 in edge aligned mode. (Source: NXP user manual for LPC1768)</div><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-6yxDSDiQrTU2o36gRTHoafXhImyj2wLPw347XHPJeEGwGv4GSHVqtuWr3H2lSd5rnkWNBta4yUwf9Nxge_tuTP7Vfpc1EyNuqXUho2ZL3qFbDkxtaAyQsZSD9n11NSudwzAC98dO9_Bj/s1600/img2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-6yxDSDiQrTU2o36gRTHoafXhImyj2wLPw347XHPJeEGwGv4GSHVqtuWr3H2lSd5rnkWNBta4yUwf9Nxge_tuTP7Vfpc1EyNuqXUho2ZL3qFbDkxtaAyQsZSD9n11NSudwzAC98dO9_Bj/s400/img2.png" width="400" /> </a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"> Figure 2: Waveform indicating the output of MCPWM channel 0 with polarity as 0 in center aligned mode. (Source: NXP user manual for LPC1768) </div><br />
<br />
For 2-channel audio generation purpose, MCPWM channels 1 and 2 were used. Follow the code below to initialize and use the MCPWM.<br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;"><span style="font-family: "Courier New", "Courier", monospace;">// Power up MCPWM</span></span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_SC->PCONP |= 1<<17;</span><span style="font-family: "Courier New", "Courier", monospace;"><span style="font-family: "Courier New", "Courier", monospace;"></span></span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><span style="font-family: "Courier New", "Courier", monospace;"><br />
</span></span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><span style="font-family: "Courier New", "Courier", monospace;"> </span></span><span style="font-family: "Courier New", "Courier", monospace;">// PCLK = CCLK (100MHz in our case)</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_SC->PCLKSEL1 |= 1<<30;</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"><br />
</span><br />
<span style="font-family: "Courier New", "Courier", monospace;">// Configuring P1.25 and P1.28 as MC1A and MC2A</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_PINCON->PINSEL3 |= (1<<18) | (1<<24); </span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Set the Limit register (MCLIM0-2 is named as MCPER0-2 in CMSIS source file)</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_MCPWM->MCPER1 = 255;</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_MCPWM->MCPER2 = 255;</span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Start MCPWM channels 1 and 2 and POLA = 1</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_MCPWM->MCCON_CLR = 0xffffffff;</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_MCPWM->MCCON_SET = (1<<10) | (1<<18) | (1<<16) | (1<<8); </span><br />
<br />
Here the reason I am using POLA = 1 is that I want average value of the output signal to be my audio signal. I am using 8-bit audio and the audio sample value 0 should give less amplitude than the value 255. So the PWM signal should stay HIGH only till it matches with the match value (audio sample) and then should become LOW.<br />
<br />
Now that the configuration is over, the only thing that is remaining is to get audio out of MC1A and MC2A. So we need to update the MCMAT1 and MCMAT2 at the PCM rate of the audio signal that needs to be played. For example we want to play a 16kHz 8-bit sample width audio (WAV file). So we need to update MCMAT1,2 once in (1/16kHz) = 62.5uS. Lets setup a timer to give an interrupt once in 62.5uS and update the match values in that interrupt.<br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Power up Timer1</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_SC->PCONP |= 1<<2;</span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// PCLK = CCLK (In my case it is 100MHz) </span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_SC->PCLKSEL0 |= 1<<4;</span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Select 16kHz as timer frequency</span><br />
<span style="font-family: "Courier New", "Courier", monospace;">// (100MHz / 16kHz) = 6250. Therefore match value should be 6249 as the timer starts counting from 0.</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_TIM1->MR0 = 6249;</span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Reset and interrupt on Match 0</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_TIM1->MCR |= (1<<0) | (1<<1);</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> </span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> // Enable Timer1 interrupt </span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> NVIC_EnableIRQ(TIMER1_IRQn);</span><br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">// Reset and Start the timer</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_TIM1->TCR = 2;</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_TIM1->TCR = 1;</span><br />
<br />
Now the interrupt routine looks like this<br />
<br />
<span style="font-family: "Courier New", "Courier", monospace;">void TIMER1_IRQHandler()</span><br />
<span style="font-family: "Courier New", "Courier", monospace;">{</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> // Update the Match registers of MCPWM </span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> // </span><span style="font-family: "Courier New", "Courier", monospace;">MCMAT0-2 is named as MCPW</span><span style="font-family: "Courier New", "Courier", monospace;">0-2 in CMSIS source file</span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> LPC_MCPWM->MCPW1 = <sample of audio channel 1>;<br />
LPC_MCPWM->MCPW2 = </span><span style="font-family: "Courier New", "Courier", monospace;"><sample of audio channel 2></span><span style="font-family: "Courier New", "Courier", monospace;">; </span><br />
<span style="font-family: "Courier New", "Courier", monospace;"> </span>}<br />
<br />
After doing this you can enjoy listening to music from LPC. You can very easily make an audio player with an SD card. See <a href="http://gvworks.blogspot.com/2011/05/wav-player-with-lpc1768-and-sd-card.html">this</a> for more information as to how to use an SD card with LPC1768. If anyone needs more help with MCPWM then post your queries in comments. I will try my best to find you the answer.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com28tag:blogger.com,1999:blog-7334599024470492852.post-7974170466358118562011-04-18T08:40:00.000-07:002011-10-13T13:14:43.738-07:00Success of 2D game console<div dir="ltr" style="text-align: left;" trbidi="on">Long time efforts have paid off and we were able to create a 2D game console for NTSC TV!! The features and specifications of the console are as follows.<br />
<br />
<a name='more'></a><br />
<ol style="text-align: left;"><li>It renders video of resolution 256x240 at 60fps.</li>
<li>NTSC composite video compatible. </li>
<li>It provides 256 shades of colors simultaneously by using 8-bit per pixel (4 for luma and 4 for chroma).</li>
<li>It uses 8x8 Tile structure. </li>
<li>It supports Tile only mode and Tile + Sprites mode.</li>
<li>It supports a background Tile World of size 20x20 TV screens (It can be extended as much as there is space in flash or RAM.</li>
<li>It can render maximum of 192 sprites per frame with a maximum of 32 sprites per line.</li>
<li>It supports transparency of sprites.</li>
</ol><br />
<ol style="text-align: left;"></ol>More to come for this game console<br />
<ol style="text-align: left;"><li> Stereo support.</li>
<li>micro SD card interface.</li>
<li>Load and flash games from micro SD card.</li>
<li>NES/SNES compatible game controllers.</li>
<li>MIDI support.</li>
</ol><br />
<ol style="text-align: left;"></ol>Some PICS of the rendered video.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy2JA3cMt-Ye9lZ3fXgK1C50BCF1yI3vSIX0YD2lYmcZYhWCumSpM9p9wEwIHdiiAqRapbEmDJnNS69s8Qm1YGPDkFXij09nD4Ne9IsEMZ9nGHOxeFt5gJjoOZ3wXjF7T2sHRUCWx_kd-K/s1600/Image0863.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh35q5zbczr_y7zem94IxF5-3o6HJaSqWgObL1YI38y2_ulpXBNGXDkFkLz72I8TvslEu70xkccjnphs4JNtDtHvd7RffRvF-YEOg-br9XfHU9pW_wOZxOGG0_Ine2RzZ3q5BU7evOwugTt/s1600/Image0864.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh35q5zbczr_y7zem94IxF5-3o6HJaSqWgObL1YI38y2_ulpXBNGXDkFkLz72I8TvslEu70xkccjnphs4JNtDtHvd7RffRvF-YEOg-br9XfHU9pW_wOZxOGG0_Ine2RzZ3q5BU7evOwugTt/s320/Image0864.jpg" width="320" /></a></div><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGEyEgP9DVfmXDy2TIID-VxwOtaUBIzau07TOSucb3XTitjYvUAvcPScuNfLZ6HLHrludI4LyAv5zO2u1RKEWC6xHAcHWngWNSj5b9WwBT_OQ6Jmw7UZ-Wj7wo5VyW3ZwN-pXo7Jvz30eC/s1600/Image0865.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGEyEgP9DVfmXDy2TIID-VxwOtaUBIzau07TOSucb3XTitjYvUAvcPScuNfLZ6HLHrludI4LyAv5zO2u1RKEWC6xHAcHWngWNSj5b9WwBT_OQ6Jmw7UZ-Wj7wo5VyW3ZwN-pXo7Jvz30eC/s320/Image0865.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1JsQM3RONNg_WyqyKHLxHv45Pjq5vyU4DLjkpVn0DHAYrtIMnJK0OzFdJNQ0coeQPv09vzZiRUv0FUjsQNSoNLrU7NbM1XTY9_0T74eVvbpDjI2DwuELzQqYkcHkgkyhjIbc_ZwI5ASp2/s1600/Image0866.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiPE_GxWsPQB4LFz1KkEj8LRx7IprO_tQyi8nKNTxtFv3M1BrDgDywMEtH27KcrYqzKvzfXibjmD643ksuWuiILIpP0g4OVbaY_25I0WXhrJIz4-zy5ZWsKQey97w7za6H6r8CKZHG7MXr/s1600/Image0868.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_XM_bGaZuE-JUyVzAwqQoICkN0jhfRlLJdkBcnkkRb4O_BNiv_xEf9WzjJ4JLCoHQUOmuPXWlHGv8XDmP8rMfjJrOh1mZX8YvieoCZYyCCSnhsFtSdWHYXVD8JV5fScs62_5RmXvSbfza/s1600/Image0869.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_XM_bGaZuE-JUyVzAwqQoICkN0jhfRlLJdkBcnkkRb4O_BNiv_xEf9WzjJ4JLCoHQUOmuPXWlHGv8XDmP8rMfjJrOh1mZX8YvieoCZYyCCSnhsFtSdWHYXVD8JV5fScs62_5RmXvSbfza/s320/Image0869.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglTZkuuQMVLLZ5B4HEjPepiZAQjPrgTQewYTIfDnt-MQ0Y6wFBA99vthkqCtvE2CNP2Xk0YN1lLRSQHwwCEtUbXHGj9b_NnqKSCj1ccbjhDYeLc4bT9Dtb9OlinNYMxVfel_DDYjWiiqoS/s1600/Image0870.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX5wCCIj4pAUJKga2hwz3z-4i8Oa0t4_wk9o_jH9WnZw0HYS5EqtZ07spDI3lvWCZ-vI4S4JcGbPnqtS8Urz7wBLNZxFf5J09y1LTcbiDG3mdmXomnTMhlXLLQV4cKC1nHn9NBOGeM225Z/s1600/Image0871.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX5wCCIj4pAUJKga2hwz3z-4i8Oa0t4_wk9o_jH9WnZw0HYS5EqtZ07spDI3lvWCZ-vI4S4JcGbPnqtS8Urz7wBLNZxFf5J09y1LTcbiDG3mdmXomnTMhlXLLQV4cKC1nHn9NBOGeM225Z/s320/Image0871.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg60Cb4JwdPgfinUwHdOenHmfhKZHnvWfVeyfyiED4iFWUjGjS0yqOEOcBL2_8S24J8RTkBEQkPgkiWUNn9_0pLiDaBS4ibHTwpRZrX1eCY-P5TscI8mWsOHah_nBFPvU53Mi0BeYc84-6g/s1600/Image0872.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigs0g8b-Nw-3qiOVq9r1hAdcOQ7arN-UNO85_oqKCUh5fXYK7AgNJMY3sGgis9SLvOBwtZXY57rLRLOHJTaDcB0yNnvl-B-Hcf2VLX2wSiTBTR8AlDOrtrt0pmTmN35NfSbY12RgH26Xe7/s1600/Image0873.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigs0g8b-Nw-3qiOVq9r1hAdcOQ7arN-UNO85_oqKCUh5fXYK7AgNJMY3sGgis9SLvOBwtZXY57rLRLOHJTaDcB0yNnvl-B-Hcf2VLX2wSiTBTR8AlDOrtrt0pmTmN35NfSbY12RgH26Xe7/s320/Image0873.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK8ZmnBT5ieLYvdCR2YsFHOr3GILFJwLGcaKiUB80Spmb9f8cU0gzXO06BhADcmMOJ5atpbFiY9DPJ3u4iN6iQXZHdCV9cEpSVxqq6ZLNb-nKciCmed-00OksRwh0HlKNvtkWhs9o1K1ei/s1600/Image0874.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8Orr1ORUV5sSqTab8Yffm24eHBctklR5OANCxOFda7ApkKLjLdk8Zif4ljEDTTcknxiz4dAFyC6X4jhcLx36nRyH2LPRedsDfRmCCkMesUTKMM_kd7F_wFi2cHjx2EudAZi0qic9V97M2/s1600/Image0875.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8Orr1ORUV5sSqTab8Yffm24eHBctklR5OANCxOFda7ApkKLjLdk8Zif4ljEDTTcknxiz4dAFyC6X4jhcLx36nRyH2LPRedsDfRmCCkMesUTKMM_kd7F_wFi2cHjx2EudAZi0qic9V97M2/s320/Image0875.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-bSYie0MSOa-RE5T_jT1Zix3JdSoe5NofqSsgJhlDvrar3zokJKvFKdOG9vW8dFICzpDeJmqmjHrrLyVGUcveR_WJQhpptzFSR5lv_VTONLwF-lOtx7_ntif4VMeW13hw2qbE3qd3I-t0/s1600/Image0876.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRbB7O-Bx4iaW4jYKgJFGn3hmWii60WXQ-jX-4_efgNrDzQKM0qAUgDAJnsBxpL6qN14pbmEiE0wJ0W85BCJBb0tAYYprOvDSa8GvC9w_JG3fzP2jz4HRe2bUVY19fRtecfuf-FCzebdfR/s1600/Image0877.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRbB7O-Bx4iaW4jYKgJFGn3hmWii60WXQ-jX-4_efgNrDzQKM0qAUgDAJnsBxpL6qN14pbmEiE0wJ0W85BCJBb0tAYYprOvDSa8GvC9w_JG3fzP2jz4HRe2bUVY19fRtecfuf-FCzebdfR/s320/Image0877.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8l2X-AoOpfJdl7V7fV2gCVbA_qG8UPG0gJU1BHL13qh3EQzZHHQf7VOmqFb0oIZ-kSGf_at6WgTnMmF8Kn7SWD3R9wdWXMvIjMy986BDruf7VLIN59iWYEp2YLVTfgnfLQoL2eMqPrpNv/s1600/Image0878.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXd1Ec-CMwyPn4GQetZkTDXPC0mC-u2b8hMPCvB-rxc3TExKY28ZofMKDxy9vmyuW2f_winnmW86pNEq2JKLpiLO74wA83_O3dethPyBbEZGmNytF_RDd02efrLeQkdHi-MopuYjYcqe3S/s1600/Image0879.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXd1Ec-CMwyPn4GQetZkTDXPC0mC-u2b8hMPCvB-rxc3TExKY28ZofMKDxy9vmyuW2f_winnmW86pNEq2JKLpiLO74wA83_O3dethPyBbEZGmNytF_RDd02efrLeQkdHi-MopuYjYcqe3S/s320/Image0879.jpg" width="320" /></a></div><br />
All those white ghosts are sprites!!<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqO4Q9lsyXiPosf0xRJyFN-P2bRGO2qzKGKEDyVqFTM2dqZ9nHqhiWUjmMpaft7FLZpHr8D8bdiYhu3sbN-jNHebsd4VCeFXGasy_yG9_ZlUArHMS42oAJQMZhrOgD3BKhLoQgs6QXCPhM/s1600/Image0880.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP_DmBrPBLptvzy1qRNTQPgJxUaVsoixUWue_Z4KAE4rJkw6DZeL_M8t5dPVo3zyG9UuUYh8rCcw_4XAAbBrM4Dl4bcV7g_4c2_s8HeDyghfA2RqD-IBUmiOE20x85DB8EnUTTi4jnqTqD/s1600/Image0881.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP_DmBrPBLptvzy1qRNTQPgJxUaVsoixUWue_Z4KAE4rJkw6DZeL_M8t5dPVo3zyG9UuUYh8rCcw_4XAAbBrM4Dl4bcV7g_4c2_s8HeDyghfA2RqD-IBUmiOE20x85DB8EnUTTi4jnqTqD/s320/Image0881.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSSuaZlJmwilC0SF7DDotQFoJH26gDWYH341GVvwR_PaaXTwcYTIbmwkpzgrLkw0g7wACGw7y7eHIiq1rOycRC4LxyT69m0BXeAFxOQObjiYy_rThytFcDpowMcipIz3T9e_dfwBfLgGjD/s1600/Image0882.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv5CglIWUVsrIdQ1X2BKEXsv06SbC5LcpdJTRsFUk1WGpvtqObDnJ7G1TPrixAZQG-E9lWUOVmOg5GZeJ-W0izd32tPiRSxmsoyFJcnPypsOI4vVliqFtV0dgBRLcRJ2l2hOCahCCjjItX/s1600/Image0883.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv5CglIWUVsrIdQ1X2BKEXsv06SbC5LcpdJTRsFUk1WGpvtqObDnJ7G1TPrixAZQG-E9lWUOVmOg5GZeJ-W0izd32tPiRSxmsoyFJcnPypsOI4vVliqFtV0dgBRLcRJ2l2hOCahCCjjItX/s320/Image0883.jpg" width="320" /></a></div><br />
<br />
Some Tech Demos of the Game Console project can be viewed here.<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/fcJU5AHl5Us?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Kq5cxBm2Yqg?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/t3oGis-U5Tw?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/6V95iItvcUQ?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<br />
A complete 2D game will be done and implemented on this system ASAP. And more importantly after the completion of this project, it will be made open source.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com4tag:blogger.com,1999:blog-7334599024470492852.post-53831122802197004962011-04-18T08:12:00.000-07:002011-10-13T13:14:15.556-07:00Easier method of color generation for NTSC Television<div dir="ltr" style="text-align: left;" trbidi="on"><span style="font-size: small;"> Please read <a href="http://msys-mv.blogspot.com/2010/11/understanding-basic-requirements-to.html">this</a> and <a href="http://msys-mv.blogspot.com/2011/01/why-is-ntsc-color-carrier-frequency.html">this</a> (optional) for better understanding before you read this post.</span><br />
<br />
<span style="font-size: small;">Few popular methods used to generate different colors for NTSC are<br />
1. using AD725 IC for RGB values to NTSC color conversion<br />
2. using a standard 3.579545MHz as the color carrier and producing different delays to get different phase and in-turn different colors in NTSC. This can be done by using a number of buffers to create delays and selecting the required color among these delayed signals by the use of a multiplexer.</span><br />
<br />
<a name='more'></a><br />
<br />
<span style="font-size: small;">The first method takes the fun out of it and the second method requires a lot of hardware. So for everyone searching for a new easier method to generate a good amount of colors for NTSC TV, you are in the right place and reading the right post!!</span><br />
<span style="font-size: small;"><br />
</span><br />
<span style="font-size: small;">The idea is very simple. It involves PWM and diodes. The number of colors that you can generate will depend on the number of double edge PWMs available in your microcontroller. In LPC1768 we can use all the 6 PWM channel outputs to generate 64 (2^6) solid colors. Taking into account the shades of luminance you can create, a lot of color shades can be created here with minimal hardware. In the Blueboard LPC1768-H there are only 5 PWM channel outputs are accessible. But currently keeping 4-bits for luma and 4-bits for chroma, only 4 channels are used.</span><br />
<span style="font-size: small;"><br />
</span><br />
<span style="font-size: small;">The idea is to generate different phases at different PWM channels and add them suitably to get different colors. To do this the LPC clock frequency should be a multiple of the color carrier 3.579454MHz. 85.90908MHz (3.579545 * 24) can be used as the PLL generates this with less error when compared to other frequencies. Now keeping</span><br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"> LPC_SC->PCLKSEL0 |= 1 << 12; // PCLK_PWM1 = CCLK</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;"> // This is the PWM time period. 24 is chosen as the CPU freq is 24 times the color carrier.</div><div style="font-family: "Courier New",Courier,monospace;"> MR0 = 24; </div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;"> LPC_PWM1->MR1 = 1;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 2 output will be high from 1 to 6 <br />
LPC_PWM1->MR2 = 6; </div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 3 output will be high from 6 to12 <br />
LPC_PWM1->MR3 = 12; </div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 4 output will be high from 12 to 16</div><div style="font-family: "Courier New",Courier,monospace;"> LPC_PWM1->MR4 = 16; </div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 5 output will be high from 16 to 24 <br />
LPC_PWM1->MR5 = 24; </div><br />
Channel 4 will be used as color burst in this case. The on time duration of it is made low in the intention of getting higher color saturation. As the on time duration of this signal is low, its average value will be lower than other channel signals. Thus higher color saturation achieved.<br />
<br />
As each channel has different phase signals, we already have 4 colors. I said earlier that we can get (2^4) 16 basic colors by using 4-bits for chroma. The extra 12 colors are obtained by adding the outputs of these 4 channels in a controlled manner. By adding channel 2 and channel 4's outputs a new phase is obtained and hence a new color. Like this we can add these 4 channels in 16 different ways and thus we can get 16 basic colors (two or three of them can be gray. For example if all channels are added or if no channel is added we get gray).<br />
<br />
Now the question is how to add these signals. Using an analog 4 channel adder is complex than the buffer method mentioned above. So what another way is there in which we can add signals? Simple answer is by shorting the wires in which those two signals are present. But shorting does not sound good as it has many disadvantages like sourcing and sinking problems of the peripherals (they might get damaged due to high currents) and influence of one signal on the other will be too high. So here is one novel method to add these colors.<br />
<br />
The novel method is to put a diode in all the signal paths and to short the outputs of these diodes!! As the diodes conduct in only one direction, both the problems stated above are solved. Now the big question is how to controll the addition? For that there is another very simple solution!! Making use of the open drain feature of the GPIO ports, we can put HIGH and LOW on the pins which are configured in open drain mode and control the addition. If an HIGH is put in an open drain output pin, that pin will be in high impedance state and if a LOW is put, the pin will be grounded and the output will be LOW. So by connecting 4 open drain GPIO pins to the PWM channel outputs we can control and generate any of the 16 basic colors at a time.<br />
The schematic of the circuit is shown below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMn7kjYxVQScozGnm_8J9OwcJUAP0kVrHr7rYOQzyLff4clFGAEVOjrb64H3ct0ywVizgaPblSEbb7DqvzFshr0kBNYFHpvQeF4MwYWRjQWXliMHTbnJLNpr41BAJxKLGVzJi3aeCVC5PO/s1600/NTSC+color+generation+by+diodes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMn7kjYxVQScozGnm_8J9OwcJUAP0kVrHr7rYOQzyLff4clFGAEVOjrb64H3ct0ywVizgaPblSEbb7DqvzFshr0kBNYFHpvQeF4MwYWRjQWXliMHTbnJLNpr41BAJxKLGVzJi3aeCVC5PO/s320/NTSC+color+generation+by+diodes.png" width="320" /></a></div><br />
If you have access to all 6 channels of PWM and are willing to assign 6-bits for chroma you can use Match Register values like<br />
<div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;"> MR0 = 24;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 1 output will be high from 24 to 4 </div><div style="font-family: "Courier New",Courier,monospace;"> MR1 = 4;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 2 output will be high from 4 to 8 </div><div style="font-family: "Courier New",Courier,monospace;"> MR2 = 8;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 3 output will be high from 8 to 12</div><div style="font-family: "Courier New",Courier,monospace;"> MR3 = 12;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 4 output will be high from 12 to 16 </div><div style="font-family: "Courier New",Courier,monospace;"> MR4 = 16;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 5 output will be high from 16 to 20 </div><div style="font-family: "Courier New",Courier,monospace;"> MR5 = 20;</div><div style="font-family: "Courier New",Courier,monospace;"> // Channel 6 output will be high from 20 to 24 </div><span style="font-family: "Courier New", "Courier", monospace;"> MR6 = 24;</span><br />
<br />
<span style="font-family: inherit;">You can keep one of the signals high for a less duration to get greater color saturation.</span><br />
<br />
<span style="font-family: inherit;">The results obtained by this method of color generation can be seen in the below pics. Here each pixel is represented by an 8-bit number out of which 4-bits are used for chroma and 4-bits for luma. Hence you can see there are 16 brightness levels and 16 basic colors. In combination there are 256 shades of colors!! </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIK1-AJEvIbA6aauPHVqG9a44xZC57NComFlJl7P1Z-0nXgR70UnoHZ9VU0WSJMWJTUbOXutyjQBAw4iuz8qD_CO41XsU3HqMOOwsHKeX58uHp8GVlw1ODn99-mxARh1CTw6KtdPlQKUD9/s1600/Image0857.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIK1-AJEvIbA6aauPHVqG9a44xZC57NComFlJl7P1Z-0nXgR70UnoHZ9VU0WSJMWJTUbOXutyjQBAw4iuz8qD_CO41XsU3HqMOOwsHKeX58uHp8GVlw1ODn99-mxARh1CTw6KtdPlQKUD9/s320/Image0857.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_643iQQMCkT7oBM59MtoUQjVuGdaIgvxa9UZuF3d43IhAESFeP-ZxLwhxaJ0zT1HMA27YfvWC3UOYMUnM_673WI64hniF8fq_5YSrGt30JwsmAHKOuFJEiRebGpO8b7ffIuU4_ZiPVE8f/s1600/Image0858.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_643iQQMCkT7oBM59MtoUQjVuGdaIgvxa9UZuF3d43IhAESFeP-ZxLwhxaJ0zT1HMA27YfvWC3UOYMUnM_673WI64hniF8fq_5YSrGt30JwsmAHKOuFJEiRebGpO8b7ffIuU4_ZiPVE8f/s320/Image0858.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkLUR0Udbdccfmiv9RpTT38VJb6RPEPiAbVVInOSBmrz_FWJffbGUSmHPKohO3qEfrMjOvk767Ywnq1OrsrqJkC3sVQtoqdWbkNvVfU1JTR2Eq-70D3rQgUFx-bu13PVD0gP6ubp4-LvWF/s1600/Image0860.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkLUR0Udbdccfmiv9RpTT38VJb6RPEPiAbVVInOSBmrz_FWJffbGUSmHPKohO3qEfrMjOvk767Ywnq1OrsrqJkC3sVQtoqdWbkNvVfU1JTR2Eq-70D3rQgUFx-bu13PVD0gP6ubp4-LvWF/s320/Image0860.jpg" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT5NI8rB6EPsy0IbhrvWGD3BJ5NqsbGjL5Maxwo0hUN49k2Cr_Yv-FYGsNr7whbQVXkbYNQ1q4LHExXVKxvtouBsrjExSO7MjO7fPIW4y-avYOQMhNkXnjMZDUwCUWK5AlFnY2gt0UYs_x/s1600/Image0861.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT5NI8rB6EPsy0IbhrvWGD3BJ5NqsbGjL5Maxwo0hUN49k2Cr_Yv-FYGsNr7whbQVXkbYNQ1q4LHExXVKxvtouBsrjExSO7MjO7fPIW4y-avYOQMhNkXnjMZDUwCUWK5AlFnY2gt0UYs_x/s320/Image0861.jpg" width="320" /></a></div><br />
<br />
A method similar to this devised and tested by me and my friend is <a href="http://sites.google.com/site/playbx/project-updates/anovelideaforgeneratingmanyanumberofcolorsforntscusingonlyone7404fewresistorsanddiodesalongwithamicrocontroller">here</a>.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com0tag:blogger.com,1999:blog-7334599024470492852.post-70074855051525837372011-01-25T18:47:00.001-08:002012-03-03T07:47:49.700-08:00DMA in LPC17xx<div dir="ltr" style="text-align: left;" trbidi="on">Direct Memory Access is a feature which allows the peripherals to access the memory directly or to transfer data to other peripherals without the help of CPU. So whenever we are using DMA, we can be doing computations on the CPU while the data transfer is taking place. Effectively the microcontroller is multitasking.<br />
<br />
LPC17xx has a General Purpose DMA (GPDMA) which has 8 channels of which each can perform unidirectional data transfer. All types of data transfers like memory-memory, memory-peripheral, peripheral-peripheral are supported. And we can prioritize the DMA transfers as we wish. It can also perform 8-bit, 16-bit and 32-bit wide transactions. If we want to transfer a stream of data that is not stored in contiguous manner, then we can use the scatter and gather feature of the DMA which uses linked list. There are many many more features available with the GPDMA out of which I will be explaining some basic features in this post. I will talk about other advanced features as and when it is required.<br />
<a name='more'></a><br />
The essential things that you need to do while configuring the DMA are<br />
<ol style="text-align: left;"><li>Select the channel to be used for data transfer based on the priority requirement (DMA channels have fixed priorities. So we should choose the channel of required priority for our use.)</li>
<li>Set the bus transfer width (8-bit, 16-bit or 32-bit)</li>
<li>Set the source and destination</li>
<li>Set the DMA request signal (The signal that will start the DMA transfer)</li>
<li>Set the endian behaviour (Little endian or Big endian)</li>
<li>Set the burst size (Number of bytes that need to be transferred continuously in one DMA transaction)</li>
<li>Set the type of transfer (Mem-Mem, Mem-Peripheral or Peripheral-Peripheral) </li>
</ol>Now let us go step by step and setup the GPDMA to perform a simple task of toggling the LED. Here lets store a series of alternating 1's and 0's in an array and then transfer it to the GPIO port for which the LED is connected through channel 0 of the DMA.<br />
<br />
Setup of the timer which generates the DMA request signal<br />
<br />
LPC_SC->PCONP |= 1 << 2; // Power up<br />
LPC_SC->PCLKSEL0 |= 0x01 << 4; // CCLK<br />
LPC_TIM1->MR0 = 1 << 25;<br />
LPC_TIM1->MCR = 1 << 1; // reset on Match Compare 0<br />
<br />
Now lets configure the DMA.<br />
1. Power up the GPDMA (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 46, pg 64)<br />
<br />
LPC_SC->PCONP |= 1 << 29;<br />
<br />
There is no need to setup the clock for DMA as we were doing for other peripherals. The system clock will be directly given to the DMA. <br />
<br />
2. Enable the GPDMA (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 557, pg 599)<br />
<br />
LPC_GPDMA->DMACConfig |= 1 << 0;<br />
<br />
If you are using big endian mode you need to set the bit 1 of DMACConfig register.<br />
<br />
3. Set the Match Compare 0 (MAT1.0 signal) as the DMA request signal<br />
<br />
LPC_GPDMA->DMACSync &= ~(1 << 10); // use MAT1.0 for Sync (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 558, pg 599)<br />
<br />
// The above line is actually not needed as DMACSync register will be zero on reset.<br />
<br />
LPC_SC->DMAREQSEL |= 1 << 2; // Timer1 Match Compare 0 as DMA request (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 559, pg 600)<br />
<br />
4. Clear the Interrupt Terminal Count Request and Interrupt Error Status register. (Writing 1 to the clear registers will clear the entry in the main register. i.e writing 0xff to DMACIntErrClr register will clear the DMACIntErrStat register)<br />
<br />
LPC_GPDMA->DMACIntErrClr |= 0xff; // (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 549, pg 596)<br />
<br />
LPC_GPDMA->DMACIntTCClear |= 0xff; // (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 547, pg 595)<br />
<br />
5. Set the source and destination addresses (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 560 and 561, pg 601)<br />
<br />
LPC_GPDMACH0->DMACCDestAddr = (uint32_t) &(LPC_GPIO1->FIOPIN3); // LED is connected to P1.29<br />
<br />
LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) &data[0]; // data[] is the array where I have stored alternating 1's and 0's<br />
<br />
6. Clear the Linked List as we are not using it. (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 562, pg 602)<br />
<br />
LPC_GPDMACH0->DMACCLLI = 0;<br />
<br />
7. Set the burst transfer size, source burst and destination burst size, source and destination width, source increment, destination increment (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 563, pg 603)<br />
<br />
In our case, let the transfer size be 200 bytes, source burst and destination burst sizes are 1, source and destination width are 8-bits and we need to do source increment and there is no need for destination increment.<br />
<br />
LPC_GPDMACH0->DMACCControl = 200 | ( 1 << 26 );<br />
<br />
8. Set the type of transfer as Memory to Peripheral and the destination request line as MAT1.0 (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 564, pg 605)<br />
<br />
LPC_GPDMACH0->DMACCConfig = ( 10 << 6 ) | ( 1 << 11); // 10 corresponds to MAT1.0 and it is selected as the destination request peripheral (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 543, pg 592)<br />
<br />
9. Enable the channel (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 564, pg 605)<br />
<br />
LPC_GPDMACH0->DMACCConfig |= 1; //enable ch0<br />
<br />
You can setup an interrupt for DMA transfer completion so that after the DMA transfer is complete and interrupt request is generated and in the interrupt service routine you need to disable the channel by writing<br />
<br />
LPC_GPDMACH0->DMACCConfig = 0; // stop ch0 dma<br />
<br />
and then repeat all the steps of configuration to setup another transaction.<br />
<br />
The compiled code which toggles the LED connected to pin P1.29 with the help of DMA is <a href="http://cortex-m3-tutorials.googlecode.com/files/LED_Blink_by_DMA.rar">here</a>.<br />
<br />
Lot more details about DMA will be discussed later as and when required. I do not know what I would be doing without DMA because I need it for almost all purposes in the Game Console project. It is being used to put out Luminance and Chrominance signals. It will be used to put out audio, SD card interface, etc etc. May be at some time I will run out of channels!!</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com32tag:blogger.com,1999:blog-7334599024470492852.post-29067250237395672022011-01-24T08:52:00.000-08:002011-10-13T13:12:33.409-07:00Using PWM on LPC17xx<div dir="ltr" style="text-align: left;" trbidi="on">PWM can be used for generating analog signals of frequency very much lower than that of the PWM frequency. LPC1768 has one PWM with six channels. There will be one timer for each PWM and this timer will be used by all channels of that PWM. Configuring the PWM is similar to that of <a href="http://msys-mv.blogspot.com/2010/11/configuring-and-playing-with-timer-of.html">configuring a timer</a>. The only difference is that we also need to specify the location of rising and falling edges for each channel that we use.<br />
<br />
<a name='more'></a>Follow the steps given below to configure the PWM as you wish.<br />
<br />
1. Power up the PWM (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 46, pg 63). The PWM will be powered up when the microcontroller resets. So unless you have powered it down, there is need to follow this step.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_SC->PCONP |= 1 << 6;</div><br />
2. Setup and provide the clock to PWM peripheral (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 40 and 42, pg 56 and 57).<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_SC->PCLKSEL0 |= 1 << 12; // PWM clock = microcontroller clock i.e the prescaler value is 1.</div><br />
3. Output pins of the microcontroller must be configured to select the PWM output pins. There is a Pin Control Module in LPC17xx which can be used to select the function of each pin and also it can be used to enable or disable the pull up and pull down registers. (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 83 and 91, pg 110 and 114)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_PINCON->PINSEL4 |= 1 << 8; // P2.4 works as PWM1 output.<br />
<br />
</div><div style="font-family: "Courier New",Courier,monospace;">LPC_PINCON->PINMODE4 |= 1 << 9; // enable neither pull up nor pull down.</div><br />
4. Set the rising and falling edge configurations as per your requirements.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjel4jY0pqopc6Gj0skCO592KCE-twEgR-cPp5sfkhdRSaD5Sd0XC_ib01knpSo_xSSVlqEfDkvjQ9IHQ5s9Ng3dn7Ao3DUb5j2Kv6tCQqqOryslDd7mQZqarpqG1rx9fPZKJ2bJ9dPHfmQ/s1600/PWM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjel4jY0pqopc6Gj0skCO592KCE-twEgR-cPp5sfkhdRSaD5Sd0XC_ib01knpSo_xSSVlqEfDkvjQ9IHQ5s9Ng3dn7Ao3DUb5j2Kv6tCQqqOryslDd7mQZqarpqG1rx9fPZKJ2bJ9dPHfmQ/s1600/PWM.jpg" width="320" /> </a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">There are 7 match registers associated with the PWM. By storing suitable values in these registers, desired waveform can be obtained. In this PWM we can control both the rising and falling edges. If we want to control both the edges then we need to use double edged control. Otherwise single edged control is sufficient. If we use double edged control then the number of channels that can be used simultaneously will be reduced, as each channel requires two match registers. In case of single edged PWM, match register MR0 is dedicated for the control of the rising edge of all channels and the remaining six match registers (MR1 to MR6) can be used to control the falling edge of the six channels. Since one of the match registers is required to store the PWM rate (MR0 in case of single edge control) only channels 2, 4 and 6 can be used simultaneously or channels 3 and 5 can be used simultaneously in case of double edge control. Channel one cannot be configured as double edged PWM when MR0 stores the value of PWM rate.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">4a. Setting the rate of the PWM.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->MR0 = 16; // PWM freq = PWM clock/16</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->MCR |= 1 << 1; // Reset timer on Match0 (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 449, pg 517)</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The timer/counter associated with the PWM resets to ONE and not ZERO. Therefore if we need a PWM frequency of (PWM clock/N), then we need to store 'N' in one of the match registers and set the timer to reset on compare with that match register. Usually MR0 is used for this purpose. For single edge control only MR0 must be used to store PWM rate.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">4b. For single edge PWM set the position of the falling edge.</div><div class="separator" style="clear: both; text-align: left;">In case of single edge control PWM, the PWM output will be high when the timer resets. Therefore we can control only the position of the falling edge. To control the falling edge of channel 'x', store the suitable compare value to MRx register.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->MR5 = 8; // PWM Duty Cycle = 0.5</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Here I am storing 8 in MR5. Therefore, now one cycle of PWM waveform consists of 16 PWM clock cycles and for 8 of them the PWM output will be high and for remaining 8 cycles it will be low. Therefore the effective signal produced is a waveform of frequency (PWM clock/16) with a duty cycle of 0.5.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">4c. For double edge control (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 443, pg 512)</div><div class="separator" style="clear: both; text-align: left;">Table 443 of LPC17xx manual shows the match register pairs that are associated with each channel. By loading suitable values to these registers, desired waveform can be obtained. We have already set the PWM rate with the help of MR0 in 4a. Now to configure say, channel 4 we need to use MR3 and MR4.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->MR3 = 4;</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->MR4 = 8;</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The PWM output toggles on each compare match. If same value is stored in both the match registers, clear takes precedence and the PWM output will become LOW irrespective of its previous state.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">5. Enable the timer/counter and PWM (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 447, pg 516)</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->TCR |= (1 << 0) | (1 << 3);</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">6. Select control mode for each channel (except channel 1) and enable the PWM output (<a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> table 451, pg 519)</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->PCR |= 1 << 4; // Configure channel 4 as double edge controlled PWM</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->PCR |= 1 << 12; // Enable PWM channel 4 output</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">LPC_PWM1->PCR |= 1 << 13; //Enable PWM channel 5 output</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">7. Additional settings</div><div class="separator" style="clear: both; text-align: left;">Additional features like interrupt on a match compare or stopping the PWM on a match compare or resetting the PWM timer/counter on a match compare can all be done by playing with the PWM Match Control Resgister (PWM1MCR). Refer table 449, pg 517 of the <a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a> for further details.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">8. Little more about interrupts</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">NVIC_EnableIRQ(PWM1_IRQn); // This will enable all interrupte pertaining to the PWM1</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;"><br />
</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">void PWM1_IRQHandler (void) </div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">{</div><div class="separator" style="clear: both; font-family: "Courier New",Courier,monospace; text-align: left;">}// This is the format in which the interrupt routine must be written</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The source of the interrupt i.e to check which match compare caused the interrupt we can check the value of the interrupt flags in the PWM Interrupt Register (PWM1IR). The bit which is HIGH in this register corresponds to the source of that interrupt. The interrupt flag bit must be cleared before exiting the interrupt routine. Otherwise another interrupt will be serviced after completing the current interrupt. To clear the interrupt flag write '1' to that bit. Writing '0' will have no effect.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The complete compiled program that configures channel 4 as double edge control PWM and channel 5 as single edge control PWM and interrupts once in every PWM cycle is <a href="http://cortex-m3-tutorials.googlecode.com/files/PWM_complete.rar">here</a>.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">I am using this PWM for the generation of sync pulses for TV and the motor control PWM for the generation of audio in the Game Console. More posts on actual Game Console implementation will be coming soon, after I explain every basic thing in LPC17xx that is required for the Game Console.</div><div class="separator" style="clear: both; text-align: left;"></div></div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com52tag:blogger.com,1999:blog-7334599024470492852.post-45074547588773108252011-01-17T03:39:00.000-08:002011-10-13T13:11:56.765-07:00Why is NTSC color carrier frequency 3.57954545 MHz and not some other number that can be remembered easily?<div dir="ltr" style="text-align: left;" trbidi="on"><span style="font-size: small;">Hello guys. I am back after a long break. Now I will continue to tell a little more about NTSC before I start writing blogs on the actual Game Console implementation on LPC1768. I would suggest you to read the <a href="http://msys-mv.blogspot.com/2010/11/understanding-basic-requirements-to.html">previous post</a> before reading this one for better understanding.</span><br />
<br />
<span style="font-size: small;">I mentioned that the NTSC color carrier frequency is 3.57954545 MHz. If I want to create a game console for NTSC TV then I need to generate this frequency and use it as the color carrier. But why is 3.57954545 MHz chosen as the carrier and not some other frequency which can be easily remembered or generated?</span><br />
<span style="font-size: small;"><b><a name='more'></a></b></span><br />
<br />
<span style="font-size: small;">Before telling the answer, I will discuss briefly about the spectrum of the video signal. Video signal has a total of 6 MHz bandwidth. 1.25 MHz is used by the vestigial side band (It is a small portion of the other side band). Of the remaining 4.75 MHz, around 0.6 MHz is allocated for the audio in the form of FM. So the reamaining 0 to 4.2 MHz band is left for video signals. This spectrum was used from the days of black and white transmission. When color transmission started, the NTSC thought of some amazing methods to incorporate color in the same bandwidth so that the black and white TVs can reject the color signal. The chroma information required around 0.6 MHz of bandwidth. So the color carrier frequency should be around (4.2 MHz - 0.6 MHz) = 3.6 MHz.</span><br />
<span style="font-size: small;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Y3XAFEA8EyrRyQut8yHOIjdXOg6E265-QAJTutG5dv7LDij8bQWXtbQr0J1PukAZKwNIJisZFHdAYzkZj68hR-PeOy3l_wvzxSWyHHhpIZCn0-mcUQbYCiv_q7OqWd7FY9pdeOi0Z92f/s1600/spec_ntsc_col.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="221" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Y3XAFEA8EyrRyQut8yHOIjdXOg6E265-QAJTutG5dv7LDij8bQWXtbQr0J1PukAZKwNIJisZFHdAYzkZj68hR-PeOy3l_wvzxSWyHHhpIZCn0-mcUQbYCiv_q7OqWd7FY9pdeOi0Z92f/s320/spec_ntsc_col.gif" width="320" /></a></span></div><span style="font-size: small;"><br />
</span><br />
<span style="font-size: small;">We just cannot use 3.6 MHz blindly. There are some other things that we need to consider. Since crominance signal, luminance signal and audio signal are all very near to each other there will be interference between them. The main concern here is the interference between the chrominance and luminance. Due to this interference the luma signal is sometimes considered as chroma signal and chroma signal as luma by the TV. This is very much visible to the naked eye. But by doing some artifacts it can made invisible!!</span><br />
<br />
<div style="font-family: inherit;"><span style="font-size: small;">If the interference in one horizontal line is complimentary to that of that in the next line, the total effect will make the interference invisible. Also if the interference in the current frame is complimentary to that in the next frame, the total effect will not be visible. To make this possible, the carrier phase must change by 180 degree for each line and also for each frame. Each scanline length in NTSC is 63.5 uS. So for carrier phase to change by 180 degree for the next line, this line must have </span><span style="font-size: small;"><b>"odd multiple of one half the scan rate"</b>s of cycles of the carrier. That is if this line contains one cycle of carrier, then it will have completed 360 degrees and starts from 0 degree in the next line. But if this line contains one and a half cycle of carrier, then it will have completed (360+180) = 540 degrees, which is equivalent to 180 degrees and start from an angle 180 degree in the next line.</span></div><br />
<span style="font-family: "Arial";"><span style="font-family: "Arial"; font-size: x-small;"><span style="font-family: "Courier New", "Courier", monospace; font-size: small;">Scan Frequency = 1 / 63.5e-6 = 15748.0315 Hz</span></span></span><br />
<br />
<span style="font-family: "Arial";"><span style="font-family: "Arial"; font-size: x-small;"><span style="font-family: "Courier New", "Courier", monospace; font-size: small;">Half of scan frequency = 7874.01575 Hz</span></span></span><br />
<br />
<span style="font-family: "Arial";"><span style="font-family: "Arial"; font-size: x-small;"><span style="font-family: "Courier New", "Courier", monospace; font-size: small;">Number of carrier cycles in 7874.01575 Hz = 3.6e6 / 7874.01575</span></span></span><br />
<span style="font-family: "Arial";"><span style="font-family: "Arial"; font-size: x-small;"><span style="font-family: "Courier New", "Courier", monospace; font-size: small;"> </span><span style="font-size: small;"><span style="font-family: "Courier New", "Courier", monospace;"> = 457.19999</span></span></span></span><br />
<br />
<br />
<div style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">We can choose 457, then we get the carrier frequency as 3.598425 MHz. But some experiments concluded that we get better results if we choose 455. But still for 455 we do not get 3.57954545 MHz as carrier frequency. There is one more thing to be considered. While implementing color NTSC frame rate was dropped to 29.97 frames per second instead of 30. So now there are (29.97 x 525) = 15734.25 lines per second. This is nothing but the line frequency. Now (15734 x 455 / 2) = 3.57954545 MHz.</span></span></span><br />
<br />
<span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">Since there are 525 lines per frame, there will be (525 x 455 / 2) = 119437.5 cycles of the color carrier. The 0.5 in the number of cycles indicates that the carrier at the start of next frame will be differing in phase from that of the one in the current frame by 180 degrees. So now we have made both interline and interframe interference invisible!!</span></span></span><br />
<br />
<span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">I mentioned in the <a href="http://msys-mv.blogspot.com/2010/11/understanding-basic-requirements-to.html">previous post</a> that in the Game Console I will be using fake progressive scanning. That is I will not be using interlaced scanning. So I get only half of the 525 scanlines = 262.5 scanlines. To utilize the advantage of the </span></span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">3.57954545 MHz carrier (i.e use the interframe artifact of NTSC i.e to get a phase difference of 180 degree for each frame) each frame should have odd number of lines. So I will be using 263 lines per frame and will be leaving 261 interlaced lines.</span></span></span><br />
<br />
<span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">So now we know the reason for choosing 3.57954545 MHz as color carrier is to </span></span></span></div><div style="font-family: Arial,Helvetica,sans-serif;"><ol><li><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">Adjust the color information in the NTSC black and white spectrum to maintain compatibility.</span></span></span></li>
<li><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">Minimize the visibility of the interference effects.</span></span></span></li>
</ol><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">For more information about this and also about PAL and SECAM visit <a href="http://www.videointerchange.com/pal_secam_conversions.htm">http://www.videointerchange.com/pal_secam_conversions.htm. </a></span></span></span><br />
<br />
</div><div style="font-family: Arial,Helvetica,sans-serif;"></div><div style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;">Special thanks to <a href="http://www.videointerchange.com/">http://www.videointerchange.com/</a> for providing very good information about the television video standards.</span></span></span><br />
<span style="font-size: small;"><span style="font-size: small;"><span style="font-family: inherit;"> </span></span></span><span style="font-size: small;"> </span></div></div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com0tag:blogger.com,1999:blog-7334599024470492852.post-43310657648023164332010-11-19T08:09:00.000-08:002011-10-13T13:11:33.197-07:00Understanding the basic requirements to display video on a CRT TV<div dir="ltr" style="text-align: left;" trbidi="on">The basic thing that attracted me towards ARM was the idea of creating a Game Console for NTSC TV. I previously made a game console for VGA monitor using AVR. But now the desire to make it better, to get greater resolution video, good quality audio and also huge number of sprite support made me start working with ARM. The basic reason for choosing LPC1768 over hundreds of microcontrollers available in the market was that this controller seems appropriate for video graphics generation purpose. The basic architecture of it is such that it makes our job simple.<br />
<a name='more'></a><br />
Before getting into the core work of the game console we need to know as to how to interface a TV with a microcontroller. What all signals does the TV except? and what are the specifications of those signals and all. So here we are discussing all the things that are required to interface a TV with LPC1768 and to display a white line (horizontal or vertical).<br />
<br />
TV consists of a total of around 525 horizontal lines (scanlines). It uses interlaced scanning. In interlaced scanning the horizontal lines are divide into even and odd lines. So scanlines 1,3,5... come under odd field and 2,4,6,... come under even field. In interlaced scanning, TV writes either to all even lines or all odd lines in one frame. But writes the complementary lines in the next frame. So effectively we require two frames to display a complete picture in interlaced scanning. You will understand interlaced scanning better by having a look at the animation below (Click the image to see the animation).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJ7jPQfEYDdXDafS0qMN0AW65V5mG5KQu735wHBOoqpoMkY9pMKA1eAg5woJAsDOJPHhxPRPJLi5iH_IyWbXXoZxsGm_6scPK7J-7qVsSD0wUNJ471HW-jq9-ubkckseQF1xzg06Y-Th4/s1600/aa-raster-1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="341" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJ7jPQfEYDdXDafS0qMN0AW65V5mG5KQu735wHBOoqpoMkY9pMKA1eAg5woJAsDOJPHhxPRPJLi5iH_IyWbXXoZxsGm_6scPK7J-7qVsSD0wUNJ471HW-jq9-ubkckseQF1xzg06Y-Th4/s400/aa-raster-1.gif" width="400" /></a></div><br />
Fake progressive scanning: Here we write the image in only even field or odd field but not in both. So effectively the frame rate got doubled!! The slight disadvantage with this method is that there will be a one scanline gap (i.e. black line) between two used scanlines. But there is no need to worry about this disadvantage. Those black lines interleaving the scanlines of the image wont be visible from the watchable distance. If you need to know as to how to use interlaced or fake progressive scanning refer link [2] after reading this tutorial.<br />
<br />
TV needs Synchronization pulses to synchronize the light beam of the TV to the correct position, Luminance setting the intensity of the display and Chrominance which decides the color and also its relative amplitude to the color burst (will discuss what a color burst is in a while) signal will decide the color saturation.<br />
<br />
In a TV the video is split into scanlines which nothing but one horizontal line on it. And each of these scanlines will be 63.5uS in length. Each scanline except the vertical sync lines consists of two parts, one is the synchronization part and another one is the rendering part. The synchronization part consists of a horizontal sync and the color burst signal which is the reference carrier of the chrominance signal. In the rendering part both luma and chroma signals will be given to the TV.<br />
<br />
To display the video correctly TV needs two syncs. One is horizontal sync and another is vertical sync. A horizontal sync is nothing but a low level pulse for 4.3uS in the 63.5uS scanline. Whenever an horizontal sync is given the beam of the TV gets focused to the left edge of the TV but the vertical position of the beam cannot be determined if the vertical sync is not provided. And a vertical sync is nothing but one or two scanlines of invert horizontal sync i.e scnalines being high for a period of (63.5uS - 4.3uS) = 59.2uS. According to the specifications in total of eight scanlines with different duty cycle wavefroms compose one vertical sync [2]. But only one scanline of inverted horizontal sync pulse gets the job done (This doesnot work if you are planning to do interlaced scanning. But it works for fake progressive scanning). If you are a person who likes to sticks to the specs you can go with the eight scanlines V-sync only. When vertical sync is given the light beam of the TV gets focused to the top of the TV. So a H-sync following a V-sync will move the beam to the top-left of the TV from where we start giving the video signals.<br />
<br />
Now we can easily give the luminance (signal with amplitude ranging from 0.3v to 1v to get black to different shades of white) and get Black and White video. But we need color video. So we need to give color burst after the horizontal sync pulse. This signal will act as a carrier phase reference for the chroma signal. This carrier frequency will be different for different standards. For NTSC it is 3.57954545 MHz, whereas for PAL and NTSC 4.43 it is 4.433618 MHz. Both the horizontal sync pulse and the color burst is in together called as blanking period. The following image shows a typical scanline.<span style="font-family: "Arial";"><span style="font-family: "Arial"; font-size: x-small;"><span style="color: lime; font-size: x-small;"><span style="color: lime; font-size: x-small;"><span style="color: white; font-family: "Verdana"; font-size: x-small;"><b></b></span></span></span></span></span><span style="font-family: "Arial";"><span class="style14"><b></b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZdys6OcFnEKzaNZP9_eXg3srPbaNNg5YRjMOYoborFbp5ZrXGrDwbf9jam2v3qfjgPTlM-HZF0ECyBszA9lzQiGnfOT8M9Nt7wBJ-3jXPUFKNu195-u8rccbYcvLvWPndJdMeHkmGS9IJ/s1600/sync-wf.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZdys6OcFnEKzaNZP9_eXg3srPbaNNg5YRjMOYoborFbp5ZrXGrDwbf9jam2v3qfjgPTlM-HZF0ECyBszA9lzQiGnfOT8M9Nt7wBJ-3jXPUFKNu195-u8rccbYcvLvWPndJdMeHkmGS9IJ/s400/sync-wf.gif" width="400" /></a></div><br />
Now the most important thing is to add color to the video. In TV the color produced will depend on the phase difference between the chroma waveform and the color burst. So to get different colors waveforms of color carrier frequency with different phases need to be sent. The saturation of the color depends upon the relative amplitude of the chroma signal w.r.t the color burst signal. The colors generated for different phase differences is shown in the below image.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih8QXSBBSbAhyYzZtm907Rn5BXn69zI4bjUcKYm_E1DaQBGYOe0z3caktEtBuOpLculyaHZmk_GJyndrnLzdPs2UXLynNMrpKL_RB1pVq2CBg7tSuQ4mMO4xsIbvWFU2WxG0qH_W_p_7eK/s1600/NTSC_vectorograph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih8QXSBBSbAhyYzZtm907Rn5BXn69zI4bjUcKYm_E1DaQBGYOe0z3caktEtBuOpLculyaHZmk_GJyndrnLzdPs2UXLynNMrpKL_RB1pVq2CBg7tSuQ4mMO4xsIbvWFU2WxG0qH_W_p_7eK/s1600/NTSC_vectorograph.png" /></a></div><br />
<br />
<br />
We can generate H-sync and V-sync pulses using PWM while the color burst and chroma is sent via SPI and luma is put out on GPIO. The detailed explanation of implementation will be written shortly.<br />
<br />
For further information on basic working of TV go to<br />
1. <a href="http://zone.ni.com/devzone/cda/tut/p/id/3020">http://zone.ni.com/devzone/cda/tut/p/id/3020</a><br />
2. <a href="http://www.retroleum.co.uk/electronics-articles/pal-tv-timing-and-voltages/">http://www.retroleum.co.uk/electronics-articles/pal-tv-timing-and-voltages/</a><br />
3. <a href="http://www.batsocks.co.uk/readme/art_SerialVideo_5.htm">http://www.batsocks.co.uk/readme/art_SerialVideo_5.htm</a><br />
4. <a href="http://graffiti.virgin.net/ljmayes.mal/var/tvsync.htm">http://graffiti.virgin.net/ljmayes.mal/var/tvsync.htm </a></div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com0tag:blogger.com,1999:blog-7334599024470492852.post-54650861076737405762010-11-17T16:07:00.000-08:002011-10-13T13:12:51.659-07:00Configuring and playing with Timer of LPC1768<div dir="ltr" style="text-align: left;" trbidi="on">After saying Hello to LPC1768 and <a href="http://gvworks.blogspot.com/2010/11/hellow-word-on-lpc1768.html">blinking an LED using delay through GPIO</a>, it is time to use the timer for blinking the LED. First let us just get the timer running and then with the help of interrupts we shall blink the LED. For all the register description we require <a href="http://ics.nxp.com/support/documents/microcontrollers/pdf/user.manual.lpc17xx.pdf">LPC17xx manual</a>. <br />
<br />
<a name='more'></a><br />
<br />
For using any of the LPC1768 peripherals, the general steps to be followed are<br />
1. Power Up the peripheral to be used.<br />
2. Set the Clock Rate for the peripheral<br />
3. Connect necessary pins using Pin Connect Block.<br />
4. Initialize the registers of the peripheral.<br />
<br />
Go to page 490 in the manual and follow the links provided there <br />
1. Powering the Timer0 (Table 46, page 63)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_SC->PCONP |= 1 << 1; //Power up Timer 0</div><br />
2. After enabling it you need to give the clock for Timer0 (Table 40, page 56. For Timer2/3 refer Table 41, page 57) Select clock as per your requirements.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_SC->PCLKSEL0 |= 1 << 3; // Clock for timer = CCLK/2</div><br />
3. Configuring the interrupt<br />
LPC1768 contains 4 match registers for each timer. These match registers can be used to reset the timer, generate interrupt, stop the timer, to generate timing signal on an external pin. Now we shall use Timer0 Match0 register to generate the interrupt.<br />
<br />
Give a suitable value to Match Register 0<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_TIM0->MR0 = 1 << 20; // Give a value suitable for the LED blinking frequency based on the clock frequency</div><br />
Configure it as to interrupt when the timer count matches the Match0 (Table 429, page 496)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_TIM0->MCR |= 1 << 0; // Interrupt on Match0 compare</div><br />
Reset the timer (Table 427, page 494)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_TIM0->TCR |= 1 << 1; // Reset Timer0</div><br />
Enable Timer interrupts<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">NVIC_EnableIRQ(TIMER0_IRQn); // Enable timer interrupt</div><br />
And finally start the timer (Table 427, page 494)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">LPC_TIM0->TCR |= 1 << 0; // Start timer</div><br />
4. Now configure the pin to which LED is connected on the GPIO port to output mode<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"> LPC_SC->PCONP |= ( 1 << 15 ); // power up GPIO</div><div style="font-family: "Courier New",Courier,monospace;"> LPC_GPIO1->FIODIR |= 1 << 29; // puts P1.29 into output mode</div><br />
5. Write the interrupt routine<br />
Give the interrupt vector as TIMER0_IRQHandler and it is very important to check the source of the interrupt inside an interrupt routine. It can be done by checking the IR register of the TIMER0. Here the source of the interrupt can be identified by looking for a bit that is high in IR. The next thing that we should do is to clear this flag. Otherwise another interrupt will be generated as soon as this interrupt is serviced as the interrupt flag will be high. (Table 426, page 493)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">void TIMER0_IRQHandler (void)</div><div style="font-family: "Courier New",Courier,monospace;">{</div><div style="font-family: "Courier New",Courier,monospace;"> if((LPC_TIM0->IR & 0x01) == 0x01) // if MR0 interrupt</div><div style="font-family: "Courier New",Courier,monospace;"> {</div><div style="font-family: "Courier New",Courier,monospace;"> LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag</div><div style="font-family: "Courier New",Courier,monospace;"> LPC_GPIO1->FIOPIN ^= 1 << 29; // Toggle the LED</div><div style="font-family: "Courier New",Courier,monospace;"> }</div><div style="font-family: "Courier New",Courier,monospace;">}</div><br />
The compiled Eclipse code of the LED blinking with the help of Timer is <a href="http://cortex-m3-tutorials.googlecode.com/files/LED_blinking_with_timer_interrupt.rar">Here</a>.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com34tag:blogger.com,1999:blog-7334599024470492852.post-64084991028832770062010-10-21T04:53:00.000-07:002011-10-29T10:10:41.548-07:00Software tools required to work with ARM<div dir="ltr" style="text-align: left;" trbidi="on">To work with any microcontroller you will require an IDE, a compiler, and a flasher or code burning program (if you are not using a bootloader). Today I will talk about the basic software requirements to start working with an ARM cored microcontroller.<br />
<br />
<a name='more'></a><br />
<br />
1. IDE (Integrated Development Environment)<br />
Eclipse-CPP_Galileo is a good IDE available freely. <a href="http://www.eclipse.org/">Eclipse</a> is basically a multi-language software development environment which is written in Java. So you will require java to run eclipse. You can download Eclipse-CPP_Galileo <a href="http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/galileosr2">here</a>. No installation is required. Just un-rar the file and start using it.<br />
<br />
2. Compiler<br />
There are many good compilers available out there. But not many of them are free and even if you get the evaluation version, there will be a code limit of 32kB or so. So we searched a lot for better free compilers available for ARM. And finally we got the <a href="http://www.codesourcery.com/">CodeSourcery</a>. CodeSourcery G++ is a complete software development environment based on the GNU Toolchain and it can be used with Eclipse IDE.You can download it <a href="http://www.codesourcery.com/sgpp/lite/arm/portal/release1294">here</a>.<br />
<br />
3. Flasher (Required if you are not using a bootloader)<br />
<a href="http://www.hjtag.com/index.html">H-JTAG</a> is a simple tool used to flash the micorcontroller through JTAG. For this you need a JTAG progammer. JTAG Wiggler is one of the simplest JTAG programmers available. To build one for yourself see <a href="http://www.frozeneskimo.com/electronics/arm-tutorials/jtag-wiggler-clone/">this</a> and <a href="http://gvworks.blogspot.com/2010/10/hello-world-from-lpc1768.html">this</a>. Or you can buy <a href="http://shop.ngxtechnologies.com/product_info.php?cPath=26&products_id=30">USB JTAG</a> or <a href="http://shop.ngxtechnologies.com/product_info.php?cPath=26&products_id=29">Parallel Port JTAG</a> programmer boards.<br />
<br />
After getting all these follow the following steps to create and run your own program on the ARM core based controller.<br />
<br />
<br />
1. Installing CodeSourcery<br />
<br />
Start the installation wizard of the CodeSourcery-arm-none-eabi.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgywLHkA0Qcdw4U_Qvtmxkg7o2GdaFYK8EsbYIEOzGxc-rhM6czuXVfpcWkfN5gIMVDdhiXKPevVuquCpvv4GWVp_xp6cg2i9slKC8RhKZgIVrQuoQDuDqmeKwPn-knyn-j4WbvMtPt7Upy/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgywLHkA0Qcdw4U_Qvtmxkg7o2GdaFYK8EsbYIEOzGxc-rhM6czuXVfpcWkfN5gIMVDdhiXKPevVuquCpvv4GWVp_xp6cg2i9slKC8RhKZgIVrQuoQDuDqmeKwPn-knyn-j4WbvMtPt7Upy/s400/1.png" width="400" /></a></div><br />
Press next and accept the terms and conditions. Choose the typical, minimal or custom installation according to your wish. Select a directory path for installation and install it. It will take 1 or 2 minutes to install.<br />
<br />
<br />
2. Using Eclipse for code development and integrating CodeSourcery with Eclipse<br />
<br />
When you open the Eclipse for the first time it will look somewhat like this.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOV05RBKORXzN9I_KE6_Vf7yHBbBomYbQKT4bbyL3W1xih_wUJ52NX-SPTibaQVh0MrHEex3dcdsgJZDbvETsVBoeG3bXc1JMwHx41BjgCb1sLLJKucypgID7Kw5FbrfPEsk81GrXyVQ0p/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOV05RBKORXzN9I_KE6_Vf7yHBbBomYbQKT4bbyL3W1xih_wUJ52NX-SPTibaQVh0MrHEex3dcdsgJZDbvETsVBoeG3bXc1JMwHx41BjgCb1sLLJKucypgID7Kw5FbrfPEsk81GrXyVQ0p/s400/2.png" width="400" /></a></div><br />
a. The CodeSourcery will be automatically integrated into the Eclipse. So there is no need to change any settings.<br />
<br />
b. Now go to NEW -> C project. Select the project type as "Makefile project -> Empty project", give a suitable project name and click FINISH.<br />
<br />
c. Now you will see a folder with the name of your project in the Project explorer window.<br />
<br />
d. You need to add the makefile, startup code, linker file etc. etc. to your folder. The makefile basically instructs the compiler as to what it should do and what all files should it create Example : BIN file, HEX file. The startup and system initialization code will initialize the PLL, will set the interrupt handlers etc. The linker file contains information as which all files should be linked and compiled together, and where should the user code start, the starting RAM address etc. So now to add these files right click on the project folder in the Project window and select IMPORT.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4gJw0h7y0Shfg2Z0sh_zQodhZxmmYcaqQZvlNyx11RCxITH0bP3V2G2i6-0Jz_RUvsDEwn7CH4c6HOGJd1a6thDfiGhBKuZ4jsMYUlqoa5gj935mqBI96-jHdDqDFgFvKZ2NEWo258K93/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4gJw0h7y0Shfg2Z0sh_zQodhZxmmYcaqQZvlNyx11RCxITH0bP3V2G2i6-0Jz_RUvsDEwn7CH4c6HOGJd1a6thDfiGhBKuZ4jsMYUlqoa5gj935mqBI96-jHdDqDFgFvKZ2NEWo258K93/s400/3.png" width="400" /></a></div><br />
<br />
Then select "File System" and click next and then add the folder where you have the startup codes and click select all or you can select only the file that are required. <a href="http://cortex-m3-tutorials.googlecode.com/files/lpc_17xx_CPP_26Apr2011.rar">Here</a> is a sample Startup requirement code for LPC1768.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyXS_B5poMC8QU0xOnGg7AkopBRKarfknbDWERZPmtqwMXG7srJGF14BhiR83hHQallCYQZHMhWnQeSemQHO0G6Z6LBkXzBRK7NwGOONahsWeo2xZCAX9-QJxl5wGtqdVzbHshJSY3KVWB/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyXS_B5poMC8QU0xOnGg7AkopBRKarfknbDWERZPmtqwMXG7srJGF14BhiR83hHQallCYQZHMhWnQeSemQHO0G6Z6LBkXzBRK7NwGOONahsWeo2xZCAX9-QJxl5wGtqdVzbHshJSY3KVWB/s400/4.png" width="400" /></a></div><br />
If you want you can change the user code starting address or frequency of operation by changing the values in LPC17xx.ld and system_LPC17xx.c respectively. A brief tutorial explaining the startup code will be written later.<br />
<br />
e. After doing this go to main.c and type your custom code. Then Build the project and burn it on to the microcontroller.<br />
<br />
<br />
3. Using H-JTAG to flash the HEX file onto the microcontroller<br />
<br />
Go to H-JTAG. If you have connected the microcontroller through JTAG you should get the info of the chip when you press refresh. If you do not see it then may be JTAG link is not connected or may be the microcontroller is not powered up. Go to INIT and disable the auto init script option. Some settings that need to be made are shown in the following pictures. Please configure your H-JTAG if you are using Parallel Port JTAG connector as shown below<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIIN8wF1uD7C8CuSJkQECjAG8yOHKsHDtcl9fpJPPmhr7gHu8W2AILdLf3ghOyFeOaSESLMU38JJ9j95h-0e2JKvn-piNcUeFEzSf0d0WUTGxnJnIJ0wQbGPSoHGvX6l5LQ4eCVPWzT8lS/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIIN8wF1uD7C8CuSJkQECjAG8yOHKsHDtcl9fpJPPmhr7gHu8W2AILdLf3ghOyFeOaSESLMU38JJ9j95h-0e2JKvn-piNcUeFEzSf0d0WUTGxnJnIJ0wQbGPSoHGvX6l5LQ4eCVPWzT8lS/s400/1.png" width="400" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh29AV6YFY-CCey0rCo0OHDS_6kcTjfQ9MAqrsUszyIG_8cNUPJLzWJasNC6EkwaLb5zNCQYPYrwog2wNunplXFMlGI8cKX5p9Vx5p6XmuogCHvuBCu9qiipAhGY4XZd8Rz1YquVAMh2hcM/s1600/2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="363" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh29AV6YFY-CCey0rCo0OHDS_6kcTjfQ9MAqrsUszyIG_8cNUPJLzWJasNC6EkwaLb5zNCQYPYrwog2wNunplXFMlGI8cKX5p9Vx5p6XmuogCHvuBCu9qiipAhGY4XZd8Rz1YquVAMh2hcM/s400/2.jpg" width="400" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDbuF1bn9ECUyo1ubgHKICz0xZlOIDKv5klTTjH0nogz708-cmwIZTlCoIOOAGCqVnJN3UHwpEoWWEHE1kioKrd7sB-f6UM7OWJjN51POLIf27-G4fL7OsQ5cxN4e0NbVrFZFz2ZIQ604F/s1600/3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDbuF1bn9ECUyo1ubgHKICz0xZlOIDKv5klTTjH0nogz708-cmwIZTlCoIOOAGCqVnJN3UHwpEoWWEHE1kioKrd7sB-f6UM7OWJjN51POLIf27-G4fL7OsQ5cxN4e0NbVrFZFz2ZIQ604F/s400/3.jpg" width="400" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjr9eRspRylMn92qBv2rbHAJ4hkvSG6qSzbtd78_XjZymdvIi67-bNzS_N7QloYx9C4tHPIPTf6wSepNtMiTeW0vGBHWTVS7_xmIQ32mKzc2Fv-o4B09NzUww3MgBp_vNtcanXNsH7wfMG/s1600/4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="333" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjr9eRspRylMn92qBv2rbHAJ4hkvSG6qSzbtd78_XjZymdvIi67-bNzS_N7QloYx9C4tHPIPTf6wSepNtMiTeW0vGBHWTVS7_xmIQ32mKzc2Fv-o4B09NzUww3MgBp_vNtcanXNsH7wfMG/s400/4.jpg" width="400" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiijQrSiq8Hikyi5oTZzVP0Rl-bly-eVZtND0kjB9Bc3cmk_DGAcX3stVVPrKZrf_Qp5iLjup7RlJkNmSOBtFeAzNKWS6vMZJbz3mFm5miMBvgtWDlgoUH-AvQokJ9zEO_twS-ogb2G7r6f/s1600/5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiijQrSiq8Hikyi5oTZzVP0Rl-bly-eVZtND0kjB9Bc3cmk_DGAcX3stVVPrKZrf_Qp5iLjup7RlJkNmSOBtFeAzNKWS6vMZJbz3mFm5miMBvgtWDlgoUH-AvQokJ9zEO_twS-ogb2G7r6f/s400/5.jpg" width="400" /></a></div><br />
Then go to H-Flasher and select the target chip.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip-pOiZSGJco8qtd4aquj9_lZnH08UYhPaiaHB4-78gr0VzP4q3pfKTxwij44K0iYX9bPYljtHJghVgWSGJ-4eDXU3ooIOWwQjXG4FF_XB30xv5NJA34tu1icQv29pkZdl2j_xe09CrLXN/s1600/6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip-pOiZSGJco8qtd4aquj9_lZnH08UYhPaiaHB4-78gr0VzP4q3pfKTxwij44K0iYX9bPYljtHJghVgWSGJ-4eDXU3ooIOWwQjXG4FF_XB30xv5NJA34tu1icQv29pkZdl2j_xe09CrLXN/s400/6.png" width="400" /></a></div><br />
The H-Flasher will not reset the controller after flashing it. So if you want the chip to reset after burning do the following setting.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBbSd6h-FUmFLLCdKZsBTl64ubvfOnP1jlB8DZb-xDW-PuUqKPvLwVB3LW8GfH3oyVoPqEbZg5GAcKC61cK-XbKt91NtouZWcUpIlBdP_vFpb_oy9XCJp2jgube5FsERNF1NClZ8RLgZgY/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBbSd6h-FUmFLLCdKZsBTl64ubvfOnP1jlB8DZb-xDW-PuUqKPvLwVB3LW8GfH3oyVoPqEbZg5GAcKC61cK-XbKt91NtouZWcUpIlBdP_vFpb_oy9XCJp2jgube5FsERNF1NClZ8RLgZgY/s400/7.png" width="400" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEismZzz3ERxx0egqRNUYndzsR7N-ajFV7_Pa5yZQbeN3o8n8iWfkCVy_ds4Vui6ZDOFMj0OQ9COthq9EUtOcCuuwgBFPxKdzxKYTlArm14hqNvn3hVm2i_YvsZvPSdxWOMGc8_VMovCd4qH/s1600/8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEismZzz3ERxx0egqRNUYndzsR7N-ajFV7_Pa5yZQbeN3o8n8iWfkCVy_ds4Vui6ZDOFMj0OQ9COthq9EUtOcCuuwgBFPxKdzxKYTlArm14hqNvn3hVm2i_YvsZvPSdxWOMGc8_VMovCd4qH/s400/8.png" width="400" /></a></div><br />
Select the HEX file and program the chip!!<br />
<br />
<br />
Other popular IDE and compiling softwares available are Keil (uVision IDE and Keil compiler), WinARM, GNU-ARM etc.<br />
<br />
The USB bootloader tutorial and the code for Secondary USB bootloader for LPC17xx (modified code for Blueboard-LPC1768-H) is available <a href="http://gvworks.blogspot.com/2010/10/usb-bootloader-for-blueboard.html">here</a>.<br />
<br />
<b>EDIT:</b><br />
The code base or the startup code that I have provided in this tutorial seems to have some problems. So please use the <a href="http://cortex-m3-tutorials.googlecode.com/files/lpc_17xx_CPP_26Apr2011.rar">modified correct startup code</a>. </div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com18tag:blogger.com,1999:blog-7334599024470492852.post-40321850592466769752010-10-20T05:49:00.000-07:002011-10-13T13:08:57.306-07:00Hello geeks<div dir="ltr" style="text-align: left;" trbidi="on">Hello, my fellow geeks. I am Thejasvi and I am here to share some of my knowledge on Embedded systems and also to get more from your side.<br />
<br />
<a name='more'></a><br />
<br />
While growing up I was fascinated by the advancement of technology that was taking place by my side. Computers and internet were new words for India. Even though mobile phones entered a little late, they proliferated like viruses and bacterias. This attracted my attention. I searched the reason for the hype these devices or technologies created. It interested me. I started searching for info as to how they work, what are their advantages or limitations and all. This motivated me to take Electronics and Communication in B.E.<br />
<br />
I am kind of a person who likes to try things practically and see the results. So I started doing some hobby projects with my friend Sagar during my second year of B.E. At first all we did was simple circuits like voltage regulator and all. Later we started working with ATmega microcontrollers. This is when our interest in hobby projects boosted. After playing a lot with it and getting familiar with it we did some simple and small projects like 1. An USB oscilloscope, 2. An IR remote control for PC and 3. A simple 2D game console. At this stage I would like to thank AVR Freaks (<a href="http://www.avrfreaks.net/">http://www.avrfreaks.net/</a>), which provided and is providing a lot of help for us and also for newbies to AVR microcontrollers.<br />
<br />
After working for nearly one and half years with AVR controllers, we decided to shift over to ARM cored fast 32-bit controllers with many many more features. Thus we ordered the Blueboard-LPC1768-H development board for LPC1768 - A Cortex-M3 based microcontroller. As this LPC1768 is a new chip, not many people have worked with it. Since there were no tutorials and guidance, we found it a little difficult to start working with LPC1768. Now we have decided to document everything we do so that it will help others who are interested to work with or who are working on ARM based controllers. And this blog is simply to document what all we do, to help others and to improve ourselves with the help of your feedback or suggestions.<br />
<br />
And most importantly, I and Sagar will share the work of documentation. So you may need to refer this blog as well as Sagar's blog (<a href="http://gvworks.blogspot.com/">http://gvworks.blogspot.com/</a>) to get all the details. To make you more comfortable we will cross link the posts in each other's blog so that you will not miss any info.</div>Thejasvihttp://www.blogger.com/profile/14026099804451521975noreply@blogger.com0