EmbeddedRelated.com
Forums

TimerB ISRs

Started by ssk2k4 November 29, 2008
Hello forum members,

I am using MSP430F1611 with CrossStudio. I want to use Timer B for
generating a PWM as well as a counting a timeout value. The PWM code
is as:

void ConfigTimerBCompare (void)
{
P4SEL &= ~0xA0;
P4SEL |= 0x20; // P4.5 - Select as TB5
functionality
P4DIR |= 0x20; // P4.5 - Select compare
as output

TBCTL = MC_0 | TBCLR; // Stop Timer
TBCCTL5 = 0x00; // CAP = 0 - Compare mode
TBCCR0 = (1024 - 1); // PWM Period/2
TBCCTL5 = OUTMOD_7; // CCR5 Set/Reset
TBCCR5 = 0x00; // CCR5 PWM duty cycle -
0x00(0%), 0xFF(25%), 0x1FF(50%), 0x2FF(75%), 0x3FF(100%)
TBCTL = CNTL_0; // 16 bit format
TBCCR5 = 38;
TBCCTL5 = CCIE; // CCR5 interrupt enabled
TBCTL = TBSSEL_1 | ID_2 | MC_3; // Clock sourceLK,
Divide by 4, Start timer in up-down mode
}

The ISR for Timer changes PWM duty cycle:
void ISR_TimerB (void) INTERRUPT[TIMERB1_VECTOR]
{
TBCCR5 = g_DACCount; // CCR5 PWM duty cycle -
0x00(0%), 0xFF(25%), 0x1FF(50%), 0x2FF(75%), 0x3FF(100%)
g_Data_Bit_High = g_Data_Bit_High^0x01;
TBCCTL5 |= CCIE; // CCR5 interrupt enabled
}

Above code uses TimerB module 5 for generating PWM. Now I want to use
TimerB module 1 for counting a value say a timeout count for other
task. How I need to configure timer for this? How do I configure the
ISR for reloading the timeout count to timer? I am confused of using
various timer modules - Timer0 to Timer6 and their interrupts. Can
anyone clarify or elaborate more on its use?

Thanks in advance.

Beginning Microcontrollers with the MSP430

> various timer modules - Timer0 to Timer6 and their interrupts. Can
> anyone clarify or elaborate more on its use?

Each Timer (A,B) has one timer channel. 0-6 are Capture/Compare channels !
Once you choose a fixed period for the PWM, that will be the reload value
for ALL C/C channels.
If you change the timeout for a different C/C channel, you will also change
the PWM period.
To independently count AND do PWM, you will need 2 timer channels. You
might be able
to use modulo-8,10,12 or 16, but you still can't have arbitrary timeout
values.
Perhaps look closer at the user's guide, it should explain it.

HTH
Kris

On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4" wrote:
> Hello forum members,
>
> I am using MSP430F1611 with CrossStudio. I want to use Timer B for
> generating a PWM as well as a counting a timeout value. The PWM code
> is as:

If you set up your timers so that they count up and roll over at
0xffff you will have much more versatility in the use of your CCR's
and they can all be asynchronous to each other.

For example, treat each edge of a PWM as an interrupt event and write
a very fast ISR that adds the next PWM edge time to the compare
register. It is important that you use unsigned int values so that the
addition will roll over with the counter.

Here is some example code that will set up the timer control registers
on a MSP430F5418. This code sets up all three timers to count up and
roll over at 0xffff. Timer A0 is used as a system time tic, timer B0
is used for a PWM output. You can mix/match any CCR channel and any
timer group however you like because all of the timers are set up the
same:
-----------------
/*
* Set up timer A and B to count up, roll over, use SMCLK
*/
TA0CTL = MC_2 | TASSEL_2;
TA1CTL = MC_2 | TASSEL_2;
TBCTL = MC_2 | TBSSEL_2;

/*
* Set up timer A0 as the system timer
*/
TA0CCR0 = 0;
TA0CCTL0 = CCIE;

/*
* Set up timer B0 PWM output.
*/
#define SET_PULSE_LOW OUTMOD_1
#define SET_PULSE_HIGH OUTMOD_5

TBCCTL0 = CCIE | SET_PULSE_LOW | OUT;
-----------------
System time-tic interrupt:
-----------------
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TimerA0 (void)
{
timerCounter++;
TA0CCR0 += (CLK_FREQUENCY / TICKS_PER_SECOND);
}
-----------------

PWM output ISR:
-----------------
#pragma vector=TIMER_B0_VECTOR
__interrupt void TimerB0 (void)
if((TBCCTL0 & OUTMOD_7) == SET_PULSE_HIGH)
{
TBCCTL0 = (CCIE | SET_PULSE_LOW);

TBCCR0 += pwmLowPeriod;
}

else

{

TBCCTL0 = (CCIE | SET_PULSE_HIGH);

TBCCR0 += pwmHighPeriod;

}
-----------------
I hope this helps -
Dave
--- In m..., wrote:
>
> > various timer modules - Timer0 to Timer6 and their interrupts. Can
> > anyone clarify or elaborate more on its use?
>
> Each Timer (A,B) has one timer channel. 0-6 are Capture/Compare
channels !
> Once you choose a fixed period for the PWM, that will be the reload
value
> for ALL C/C channels.
> If you change the timeout for a different C/C channel, you will also
change
> the PWM period.
> To independently count AND do PWM, you will need 2 timer channels. You
> might be able
> to use modulo-8,10,12 or 16, but you still can't have arbitrary timeout
> values.
> Perhaps look closer at the user's guide, it should explain it.
>
> HTH
> Kris
>
> On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4" wrote:
> > Hello forum members,
> >
> > I am using MSP430F1611 with CrossStudio. I want to use Timer B for
> > generating a PWM as well as a counting a timeout value. The PWM code
> > is as:
>

Hello Dave,

Thanks for your kind reply. In your code, you are using two timers
(timer A and B) and their respective interrupts. My question is can I
use either Timer for doing both PWM as well as counter - e.g. two
modules TBCCR3 as counter and TBCCR5 as PWM? If yes, how the ISR of
timer B will be configured to handle both the cases?

Thanks in advance.

--- In m..., "desertrc_tucson" wrote:
>
> If you set up your timers so that they count up and roll over at
> 0xffff you will have much more versatility in the use of your CCR's
> and they can all be asynchronous to each other.
>
> For example, treat each edge of a PWM as an interrupt event and
write
> a very fast ISR that adds the next PWM edge time to the compare
> register. It is important that you use unsigned int values so that
the
> addition will roll over with the counter.
>
> Here is some example code that will set up the timer control
registers
> on a MSP430F5418. This code sets up all three timers to count up and
> roll over at 0xffff. Timer A0 is used as a system time tic, timer B0
> is used for a PWM output. You can mix/match any CCR channel and any
> timer group however you like because all of the timers are set up
the
> same:
> -----------------
> /*
> * Set up timer A and B to count up, roll over, use SMCLK
> */
> TA0CTL = MC_2 | TASSEL_2;
> TA1CTL = MC_2 | TASSEL_2;
> TBCTL = MC_2 | TBSSEL_2;
>
> /*
> * Set up timer A0 as the system timer
> */
> TA0CCR0 = 0;
> TA0CCTL0 = CCIE;
>
> /*
> * Set up timer B0 PWM output.
> */
> #define SET_PULSE_LOW OUTMOD_1
> #define SET_PULSE_HIGH OUTMOD_5
>
> TBCCTL0 = CCIE | SET_PULSE_LOW | OUT;
> -----------------
> System time-tic interrupt:
> -----------------
> #pragma vector=TIMER0_A0_VECTOR
> __interrupt void TimerA0 (void)
> {
> timerCounter++;
> TA0CCR0 += (CLK_FREQUENCY / TICKS_PER_SECOND);
> }
> -----------------
>
> PWM output ISR:
> -----------------
> #pragma vector=TIMER_B0_VECTOR
> __interrupt void TimerB0 (void)
> if((TBCCTL0 & OUTMOD_7) == SET_PULSE_HIGH)
> {
> TBCCTL0 = (CCIE |
SET_PULSE_LOW);
>
> TBCCR0 +pwmLowPeriod;
> }

>
>
else
>
>
{
>
> TBCCTL0 = (CCIE |
SET_PULSE_HIGH);
>
> TBCCR0 +pwmHighPeriod;
>
> }
> -----------------
> I hope this helps -
> Dave
> --- In m..., wrote:
> >
> > > various timer modules - Timer0 to Timer6 and their interrupts.
Can
> > > anyone clarify or elaborate more on its use?
> >
> > Each Timer (A,B) has one timer channel. 0-6 are Capture/Compare
> channels !
> > Once you choose a fixed period for the PWM, that will be the
reload
> value
> > for ALL C/C channels.
> > If you change the timeout for a different C/C channel, you will
also
> change
> > the PWM period.
> > To independently count AND do PWM, you will need 2 timer
channels. You
> > might be able
> > to use modulo-8,10,12 or 16, but you still can't have arbitrary
timeout
> > values.
> > Perhaps look closer at the user's guide, it should explain it.
> >
> > HTH
> > Kris
> >
> > On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4" wrote:
> > > Hello forum members,
> > >
> > > I am using MSP430F1611 with CrossStudio. I want to use Timer B
for
> > > generating a PWM as well as a counting a timeout value. The PWM
code
> > > is as:
>
When the timers are allowed to roll over at max count then it does not
matter which CCR you use, and you can mix and match timer groups if you
want. In the previous example code, change the TIMER_B0 interrupt to
TIMER_B1 and read TBIV in the ISR to determine which CCR generated the
interrupt. When TBIV == 6 then you are dealing with TBCCR3. When TBIV =10 then you deal with TBCCR5. Other than that the code is the same as
in the previous example with your respective CCR registers.

Dave
--- In m..., "ssk2k4" wrote:
>
> Hello Dave,
>
> Thanks for your kind reply. In your code, you are using two timers
> (timer A and B) and their respective interrupts. My question is can I
> use either Timer for doing both PWM as well as counter - e.g. two
> modules TBCCR3 as counter and TBCCR5 as PWM? If yes, how the ISR of
> timer B will be configured to handle both the cases?
>
> Thanks in advance.
>
> --- In m..., "desertrc_tucson" dcoombs@ wrote:
> >
> > If you set up your timers so that they count up and roll over at
> > 0xffff you will have much more versatility in the use of your CCR's
> > and they can all be asynchronous to each other.
> >
> > For example, treat each edge of a PWM as an interrupt event and
> write
> > a very fast ISR that adds the next PWM edge time to the compare
> > register. It is important that you use unsigned int values so that
> the
> > addition will roll over with the counter.
> >
> > Here is some example code that will set up the timer control
> registers
> > on a MSP430F5418. This code sets up all three timers to count up and
> > roll over at 0xffff. Timer A0 is used as a system time tic, timer B0
> > is used for a PWM output. You can mix/match any CCR channel and any
> > timer group however you like because all of the timers are set up
> the
> > same:
> > -----------------
> > /*
> > * Set up timer A and B to count up, roll over, use SMCLK
> > */
> > TA0CTL = MC_2 | TASSEL_2;
> > TA1CTL = MC_2 | TASSEL_2;
> > TBCTL = MC_2 | TBSSEL_2;
> >
> > /*
> > * Set up timer A0 as the system timer
> > */
> > TA0CCR0 = 0;
> > TA0CCTL0 = CCIE;
> >
> > /*
> > * Set up timer B0 PWM output.
> > */
> > #define SET_PULSE_LOW OUTMOD_1
> > #define SET_PULSE_HIGH OUTMOD_5
> >
> > TBCCTL0 = CCIE | SET_PULSE_LOW | OUT;
> > -----------------
> >
> >
> > System time-tic interrupt:
> > -----------------
> > #pragma vector=TIMER0_A0_VECTOR
> > __interrupt void TimerA0 (void)
> > {
> > timerCounter++;
> > TA0CCR0 += (CLK_FREQUENCY / TICKS_PER_SECOND);
> > }
> > -----------------
> >
> > PWM output ISR:
> > -----------------
> > #pragma vector=TIMER_B0_VECTOR
> > __interrupt void TimerB0 (void)
> > if((TBCCTL0 & OUTMOD_7) == SET_PULSE_HIGH)
> > {
> > TBCCTL0 = (CCIE |
> SET_PULSE_LOW);
> >
> > TBCCR0 +> pwmLowPeriod;
> > }
>
> >
> >
> else
> >
> >
> {
> >
> > TBCCTL0 = (CCIE |
> SET_PULSE_HIGH);
> >
> > TBCCR0 +> pwmHighPeriod;
> >
> > }
> > -----------------
> >
> >
> > I hope this helps -
> > Dave
> >
> >
> > --- In m..., wrote:
> > >
> > > > various timer modules - Timer0 to Timer6 and their interrupts.
> Can
> > > > anyone clarify or elaborate more on its use?
> > >
> > > Each Timer (A,B) has one timer channel. 0-6 are Capture/Compare
> > channels !
> > > Once you choose a fixed period for the PWM, that will be the
> reload
> > value
> > > for ALL C/C channels.
> > > If you change the timeout for a different C/C channel, you will
> also
> > change
> > > the PWM period.
> > > To independently count AND do PWM, you will need 2 timer
> channels. You
> > > might be able
> > > to use modulo-8,10,12 or 16, but you still can't have arbitrary
> timeout
> > > values.
> > > Perhaps look closer at the user's guide, it should explain it.
> > >
> > > HTH
> > > Kris
> > >
> > > On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4" wrote:
> > > > Hello forum members,
> > > >
> > > > I am using MSP430F1611 with CrossStudio. I want to use Timer B
> for
> > > > generating a PWM as well as a counting a timeout value. The PWM
> code
> > > > is as:
> > >
>
When using TIMER_B1 interrupt, be sure to use switch(TBIV) to read the
TBIV value, because each time TBIV is read, the interrupt with the
higest priority gets cleared (the corresponding IFG is set to 0) which
immediately changes the TBIV value. Using if()s will not work.

Michael K.

--- In m..., "desertrc_tucson" wrote:
>
> When the timers are allowed to roll over at max count then it does not
> matter which CCR you use, and you can mix and match timer groups if you
> want. In the previous example code, change the TIMER_B0 interrupt to
> TIMER_B1 and read TBIV in the ISR to determine which CCR generated the
> interrupt. When TBIV == 6 then you are dealing with TBCCR3. When TBIV => 10 then you deal with TBCCR5. Other than that the code is the same as
> in the previous example with your respective CCR registers.
>
> Dave
> --- In m..., "ssk2k4" wrote:
> >
> > Hello Dave,
> >
> > Thanks for your kind reply. In your code, you are using two timers
> > (timer A and B) and their respective interrupts. My question is can I
> > use either Timer for doing both PWM as well as counter - e.g. two
> > modules TBCCR3 as counter and TBCCR5 as PWM? If yes, how the ISR of
> > timer B will be configured to handle both the cases?
> >
> > Thanks in advance.
> >
> > --- In m..., "desertrc_tucson" dcoombs@ wrote:
> > >
> > > If you set up your timers so that they count up and roll over at
> > > 0xffff you will have much more versatility in the use of your CCR's
> > > and they can all be asynchronous to each other.
> > >
> > > For example, treat each edge of a PWM as an interrupt event and
> > write
> > > a very fast ISR that adds the next PWM edge time to the compare
> > > register. It is important that you use unsigned int values so that
> > the
> > > addition will roll over with the counter.
> > >
> > > Here is some example code that will set up the timer control
> > registers
> > > on a MSP430F5418. This code sets up all three timers to count up and
> > > roll over at 0xffff. Timer A0 is used as a system time tic, timer B0
> > > is used for a PWM output. You can mix/match any CCR channel and any
> > > timer group however you like because all of the timers are set up
> > the
> > > same:
> > > -----------------
> > > /*
> > > * Set up timer A and B to count up, roll over, use SMCLK
> > > */
> > > TA0CTL = MC_2 | TASSEL_2;
> > > TA1CTL = MC_2 | TASSEL_2;
> > > TBCTL = MC_2 | TBSSEL_2;
> > >
> > > /*
> > > * Set up timer A0 as the system timer
> > > */
> > > TA0CCR0 = 0;
> > > TA0CCTL0 = CCIE;
> > >
> > > /*
> > > * Set up timer B0 PWM output.
> > > */
> > > #define SET_PULSE_LOW OUTMOD_1
> > > #define SET_PULSE_HIGH OUTMOD_5
> > >
> > > TBCCTL0 = CCIE | SET_PULSE_LOW | OUT;
> > > -----------------
> > >
> > >
> > > System time-tic interrupt:
> > > -----------------
> > > #pragma vector=TIMER0_A0_VECTOR
> > > __interrupt void TimerA0 (void)
> > > {
> > > timerCounter++;
> > > TA0CCR0 += (CLK_FREQUENCY / TICKS_PER_SECOND);
> > > }
> > > -----------------
> > >
> > > PWM output ISR:
> > > -----------------
> > > #pragma vector=TIMER_B0_VECTOR
> > > __interrupt void TimerB0 (void)
> > > if((TBCCTL0 & OUTMOD_7) == SET_PULSE_HIGH)
> > > {
> > > TBCCTL0 = (CCIE |
> > SET_PULSE_LOW);
> > >
> > > TBCCR0 +> > pwmLowPeriod;
> > > }
> >
> > >
> > >
> > else
> > >
> > >
> > {
> > >
> > > TBCCTL0 = (CCIE |
> > SET_PULSE_HIGH);
> > >
> > > TBCCR0 +> > pwmHighPeriod;
> > >
> > > }
> > > -----------------
> > >
> > >
> > > I hope this helps -
> > > Dave
> > >
> > >
> > > --- In m..., wrote:
> > > >
> > > > > various timer modules - Timer0 to Timer6 and their interrupts.
> > Can
> > > > > anyone clarify or elaborate more on its use?
> > > >
> > > > Each Timer (A,B) has one timer channel. 0-6 are Capture/Compare
> > > channels !
> > > > Once you choose a fixed period for the PWM, that will be the
> > reload
> > > value
> > > > for ALL C/C channels.
> > > > If you change the timeout for a different C/C channel, you will
> > also
> > > change
> > > > the PWM period.
> > > > To independently count AND do PWM, you will need 2 timer
> > channels. You
> > > > might be able
> > > > to use modulo-8,10,12 or 16, but you still can't have arbitrary
> > timeout
> > > > values.
> > > > Perhaps look closer at the user's guide, it should explain it.
> > > >
> > > > HTH
> > > > Kris
> > > >
> > > > On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4" wrote:
> > > > > Hello forum members,
> > > > >
> > > > > I am using MSP430F1611 with CrossStudio. I want to use Timer B
> > for
> > > > > generating a PWM as well as a counting a timeout value. The PWM
> > code
> > > > > is as:
> > > >
> > >
>
Hello Dave and Michael,

Thank you very much for your kind replies. I somehow forgot to look
TBIV reg. Thanks again for guiding. The code is working now.
Keep helping.........

SSK

--- In m..., "tintronic" wrote:
>
> When using TIMER_B1 interrupt, be sure to use switch(TBIV) to read
the
> TBIV value, because each time TBIV is read, the interrupt with the
> higest priority gets cleared (the corresponding IFG is set to 0)
which
> immediately changes the TBIV value. Using if()s will not work.
>
> Michael K.
>
> --- In m..., "desertrc_tucson" wrote:
> >
> > When the timers are allowed to roll over at max count then it
does not
> > matter which CCR you use, and you can mix and match timer groups
if you
> > want. In the previous example code, change the TIMER_B0 interrupt
to
> > TIMER_B1 and read TBIV in the ISR to determine which CCR
generated the
> > interrupt. When TBIV == 6 then you are dealing with TBCCR3. When
TBIV => > 10 then you deal with TBCCR5. Other than that the code is the
same as
> > in the previous example with your respective CCR registers.
> >
> > Dave
> >
> >
> > --- In m..., "ssk2k4" wrote:
> > >
> > > Hello Dave,
> > >
> > > Thanks for your kind reply. In your code, you are using two
timers
> > > (timer A and B) and their respective interrupts. My question is
can I
> > > use either Timer for doing both PWM as well as counter - e.g.
two
> > > modules TBCCR3 as counter and TBCCR5 as PWM? If yes, how the
ISR of
> > > timer B will be configured to handle both the cases?
> > >
> > > Thanks in advance.
> > >
> > > --- In m..., "desertrc_tucson" dcoombs@ wrote:
> > > >
> > > > If you set up your timers so that they count up and roll over
at
> > > > 0xffff you will have much more versatility in the use of your
CCR's
> > > > and they can all be asynchronous to each other.
> > > >
> > > > For example, treat each edge of a PWM as an interrupt event
and
> > > write
> > > > a very fast ISR that adds the next PWM edge time to the
compare
> > > > register. It is important that you use unsigned int values so
that
> > > the
> > > > addition will roll over with the counter.
> > > >
> > > > Here is some example code that will set up the timer control
> > > registers
> > > > on a MSP430F5418. This code sets up all three timers to count
up and
> > > > roll over at 0xffff. Timer A0 is used as a system time tic,
timer B0
> > > > is used for a PWM output. You can mix/match any CCR channel
and any
> > > > timer group however you like because all of the timers are
set up
> > > the
> > > > same:
> > > > -----------------
> > > > /*
> > > > * Set up timer A and B to count up, roll over, use SMCLK
> > > > */
> > > > TA0CTL = MC_2 | TASSEL_2;
> > > > TA1CTL = MC_2 | TASSEL_2;
> > > > TBCTL = MC_2 | TBSSEL_2;
> > > >
> > > > /*
> > > > * Set up timer A0 as the system timer
> > > > */
> > > > TA0CCR0 = 0;
> > > > TA0CCTL0 = CCIE;
> > > >
> > > > /*
> > > > * Set up timer B0 PWM output.
> > > > */
> > > > #define SET_PULSE_LOW OUTMOD_1
> > > > #define SET_PULSE_HIGH OUTMOD_5
> > > >
> > > > TBCCTL0 = CCIE | SET_PULSE_LOW | OUT;
> > > > -----------------
> > > >
> > > >
> > > > System time-tic interrupt:
> > > > -----------------
> > > > #pragma vector=TIMER0_A0_VECTOR
> > > > __interrupt void TimerA0 (void)
> > > > {
> > > > timerCounter++;
> > > > TA0CCR0 += (CLK_FREQUENCY / TICKS_PER_SECOND);
> > > > }
> > > > -----------------
> > > >
> > > > PWM output ISR:
> > > > -----------------
> > > > #pragma vector=TIMER_B0_VECTOR
> > > > __interrupt void TimerB0 (void)
> > > > if((TBCCTL0 & OUTMOD_7) == SET_PULSE_HIGH)
> > > > {
> > > > TBCCTL0 = (CCIE |
> > > SET_PULSE_LOW);
> > > >
> > > > TBCCR0 +> > > pwmLowPeriod;
> > > > }
> > >
> > > >
> > > >
> > > else
> > > >
> > > >
> > > {
> > > >
> > > > TBCCTL0 = (CCIE |
> > > SET_PULSE_HIGH);
> > > >
> > > > TBCCR0 +> > > pwmHighPeriod;
> > > >
> > > > }
> > > > -----------------
> > > >
> > > >
> > > > I hope this helps -
> > > > Dave
> > > >
> > > >
> > > > --- In m..., wrote:
> > > > >
> > > > > > various timer modules - Timer0 to Timer6 and their
interrupts.
> > > Can
> > > > > > anyone clarify or elaborate more on its use?
> > > > >
> > > > > Each Timer (A,B) has one timer channel. 0-6 are
Capture/Compare
> > > > channels !
> > > > > Once you choose a fixed period for the PWM, that will be the
> > > reload
> > > > value
> > > > > for ALL C/C channels.
> > > > > If you change the timeout for a different C/C channel, you
will
> > > also
> > > > change
> > > > > the PWM period.
> > > > > To independently count AND do PWM, you will need 2 timer
> > > channels. You
> > > > > might be able
> > > > > to use modulo-8,10,12 or 16, but you still can't have
arbitrary
> > > timeout
> > > > > values.
> > > > > Perhaps look closer at the user's guide, it should explain
it.
> > > > >
> > > > > HTH
> > > > > Kris
> > > > >
> > > > > On Sat, 29 Nov 2008 06:17:35 -0000, "ssk2k4"
wrote:
> > > > > > Hello forum members,
> > > > > >
> > > > > > I am using MSP430F1611 with CrossStudio. I want to use
Timer B
> > > for
> > > > > > generating a PWM as well as a counting a timeout value.
The PWM
> > > code
> > > > > > is as:
> > > > >
> > > >
> > >
>