electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Articles  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links  |  Store
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
Live streaming at radio.electro-music.com

  host / artist show at your time
<on air> Various Artists ~ 2014 Autumnal Equinox ~ live streaming radio ~
Please visit the chat
 Forum index » DIY Hardware and Software » Les Hall's Projects including eChucK
Programming the dsPIC Chip
Post new topic   Reply to topic Moderators: Inventor
Page 1 of 1 [5 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 5978
Location: San Antonio, Tx, USA
Audio files: 258

PostPosted: Wed Mar 25, 2009 11:44 pm    Post subject: Programming the dsPIC Chip
Subject description: what I learned about how to do it
Reply with quote  Mark this post and the followings unread

Hi folks,

I thought I would do a little demystifying about the microchip MPLAB IDE with C language that will be used for EChucK software development. It took me about three solid days of work or more to go through all the documentation and some tutorials to get to the point that I could write my first program. I'll help you skip some of that effort by explaining at least part of it in this post.

To start with, you find a template file and copy it into a directory named after your project. Then you open up MPLAB and run the Project Wizard to set up the device. In the project wizard you select the device which is a dsPIC33FJ12GP201 chip, and you also select your directory and toolset. Then you copy the template file into your project and you're finished with the Project Manager.

Next you open up your template and edit it. The code below shows the first example program that I wrote with most of the template comments removed:

Code:

#include <p33FJ12GP201>
#include <timer>
#include <outcompare>
#include <ports>

#define TIMER2PERIOD 737  /* 10 kHz */

int counter;  /* counts processor cycles */
unsigned int outputValue;  /* holds the output value */

int main ( void )
{
/* configure output compare */
outputValue = TIMER2PERIOD / 2;
CloseOC1();
ConfigIntOC1(OC_INT_OFF & OC_INT_PRIOR_5);
OpenOC1(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_ENABLE,
   outputValue, outputValue);

/* configure timer2 */
CloseTimer2();
ConfigIntTimer2(T2_INT_PRIOR_1 & T2_INT_OFF);
OpenTimer2(T2_ON & T2_IDLE_CON & T2_GATE_OFF & T2_PS_1_1 &
   T2_SOURCE_INT, TIMER2PERIOD);

/* configure ports */
__builtin_write_OSCCONL(0x00);
TRISB = 0x0093;
RPOR4 = 0x1212;
RPOR7 = 0x1212;
__builtin_write_OSCCONL(0x40);

/* infinite loop */
while (1)
   counter++;
}


I will describe this code in the next post.

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 5978
Location: San Antonio, Tx, USA
Audio files: 258

PostPosted: Wed Mar 25, 2009 11:54 pm    Post subject: Reply with quote  Mark this post and the followings unread

OK, let's look at the #include section:

Code:

#include <p33FJ12GP201>
#include <timer>
#include <outcompare>
#include <ports>


the first line includes the header file for the device which puts all the device specific constants and other stuff into your program. The remaining lines include the stuff you need to run the timers, the output compare module, and the ports. Actually I think the ports header file is unnecessary for this program, oops!

Next let's look at the constant and variable definitions.

Code:

#define TIMER2PERIOD 737  /* 10 kHz */

int counter;  /* counts processor cycles */
unsigned int outputValue;  /* holds the output value */


The #define statement defines a constant which we will use in the program, and the next two lines define variables that we will use. The counter variable is not important as it just counts time in an infinite loop and could even be replaced with a NOP (no operation) instruction. The outputValue variable will hold the output value that defines how many clock cycles the PWM (Pulse Width Modulation) signal will have as a true value, with the rest of the period being a false value.

I will describe the main program in the next post.

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 5978
Location: San Antonio, Tx, USA
Audio files: 258

PostPosted: Thu Mar 26, 2009 12:09 am    Post subject: Reply with quote  Mark this post and the followings unread

In the main program we configure the output compare 1 module, configure the timer 2 module, then go into an infinite loop while the two configured modules do their thing eternally. Here is the configuration section for the output compare:

Code:

/* configure output compare */
outputValue = TIMER2PERIOD / 2;
CloseOC1();
ConfigIntOC1(OC_INT_OFF & OC_INT_PRIOR_5);
OpenOC1(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_ENABLE,
   outputValue, outputValue);


For our demo we want an approximately 50% duty cycle, so we define outputValue to be the timer period divided by two. The division will be done to the constant at compile time and will not use the DSP math engine in the dsPIC.

Next we make three function calls that configure the output compare 1 module. Now, as is explained in the docs, the configuration bits of these functions are all defined in an interesting way. What you do is you select from a list of alternate values for each configuration bit or bit set which are defined as constants, then you just AND them all together. We begin with the CloseOC1() function which shuts off output compare 1 so that we can configure it. Then we call ConfigIntOC1() to configure the interrupts of output compare 1, and finally we call OpenOC1() to actually configure the output compare 1 peripheral and tell it to go do it's job for us.

The configuration bits of ConfigintOC1() turn off the interrupt and also set it to an interrupt priority of 5. The configuration bits of OpenOC1() set the idle mode behavior as continuous, set timer 2 as the timing source, and select PWM with no interrupt as the mode of operation. The outputValue parameters of the function call load the outputValue variable into the two internal registers of the output compare 1 peripheral.

So in summary, we told it to operate without generating interrupts, keep running even if the processor goes idle, and generate a PWM waveform with a period of about 50%.

I will describee the timer 2 configuration in the next post.

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 5978
Location: San Antonio, Tx, USA
Audio files: 258

PostPosted: Thu Mar 26, 2009 12:17 am    Post subject: Reply with quote  Mark this post and the followings unread

Here is the code that configures timer 2:

Code:

/* configure timer2 */
CloseTimer2();
ConfigIntTimer2(T2_INT_PRIOR_1 & T2_INT_OFF);
OpenTimer2(T2_ON & T2_IDLE_CON & T2_GATE_OFF & T2_PS_1_1 &
   T2_SOURCE_INT, TIMER2PERIOD);


What we do is we call CloseTimer2() to shut off timer 2 so we can configure it, then we shut off the timer 2 interrupts with ConfigIntTimer2(), and then we kickstart timer 2 with the OpenTimer2() function call.

The configuration bits of the ConfigIntTimer2() function set it for interrupt priority 1 and shut off the interrupt. The configuration bits for OpenTimer2() turn the timer on, tell it to run continuously when the processor is in idle mode, shut off the gate, set the clock prescale divider to 1, and set the clock source to internal. Then we tell it what the timer period is using the constant that we defined at the beginning of the program.

So what we are telling timer 2 to do is to count from 0 to 737 and then roll over back to zero, and to do this perpetually without ever stopping.

I will describe the final program operation in the next post.

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 5978
Location: San Antonio, Tx, USA
Audio files: 258

PostPosted: Thu Mar 26, 2009 12:30 am    Post subject: Reply with quote  Mark this post and the followings unread

The rest of the program is just an infinite while loop that eternally increments the counter variable, which is done just to burn a CPU cycle forever. The counter variable is actually never used. OK, so what we have done here is configure two peripherals to operate together and generate a 50% duty cycle square wave for us over and over for as long as the processor is powered up.

The way it works is that timer 2 counts out the period of the PWM waveform, then output compare 1 monitors timer to and compares the count of timer 2 with a threshold value of 737 / 2. It begins by outputting a one and then when the threshold value is reached it outputs a zero.

I coded it up this way because this is how the dsPIC chips will output their analog values, as PWm signals that are digital but can be converted into analog levels with a simple passive low-pass filter on the output PWM signal. Oh, I almost forgot to describe the I/O pin configuration code, shown below:

Code:

/* configure ports */
__builtin_write_OSCCONL(0x00);
TRISB = 0x0093;
RPOR4 = 0x1212;
RPOR7 = 0x1212;
__builtin_write_OSCCONL(0x40);


What happens here is the the builtin write function unlocks the port configuration registers, we write in our port information, and then another call to the builtin write function locks the port registers. The TRISB assignment sets the four output pins to be outputs, and the RPORx assignments tell all four of the output pins to send out the output compare signal.

The idea here obviously is that we could write a program that has timer 2 running at the start and then receives outputValue values and periodically resets the output compare 1 peripheral to send out a PWM signal that corresponds to those values. So over time we would get a PWM signal that represented the actual analog out value.

This concludes my little tutorial on how the program works, I hope you enjoyed it. Please feel free to comment on whatever you like, and happy programming!

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic Moderators: Inventor
Page 1 of 1 [5 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » Les Hall's Projects including eChucK
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum
e-m mkii

Please support our site. If you click through and buy from
our affiliate partners, we earn a small commission.


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use