EmbeddedRelated.com
Forums

LaunchPad -- DCO FLL, LFXT1, and 9600 bps RS232 -- computed clock values

Started by Jon Kirwan May 27, 2011
I wanted to automatically generate certain timing values used
by LaunchPad-targeted code. The purpose is to operate a
software FLL on the MSP430G22x1 cpu, which requires one
integer multiplier, and to properly operate the asynchronous
serial port communications (to the virtual COM port on a PC)
with another integer divisor. The way I chose to run the
serial communications was to divide SMCLK/MCLK down to twice
the serial port rate. That fact explains the (2*RS232_RATE)
you will see in the example code below.

Because better precision is achieved this way, LFXT1 is
divided down by 8 in the code so that the larger possible
values of SMCLK may be counted. The algorithm below assumes
this divide-by-8 case as shown in the (LFXT1_FREQ/8) you will
also see in the example code below.

So SMCLK/MCLK must be an integer multiple of some divided-
down LFXT1 rate (ACLK) and it must *also* be an integer
multiple of two times the serial rate. The result is two
very useful integer count values... one used as a multiplier
for the FLL, one used as a divider from that to get the
asynchronous serial clock.

(It was in developing this, that I encountered the assembler
bug.)

I don't know if anyone else can use this, but I figured I'd
dump it out there. It works quite nicely on my application.
And I've tested various variations and had the application
run just fine (and operate the DCO correctly, as well) for a
variety of attempted values.

Just something that may help those doing LaunchPad hobby
stuff. No copyright is retained here (as if I had much
control over that.) And of course, it is offered without
warranty, too!

(The REPT 6 used below usually isn't required as it settles
long before 6 iterations. So the 6 is non-critical. Use 2
or 3, if comfortable. I just set the 6, arbitrarily.)

This is for a Timer A2 device. I believe the maximum rate
that can be used with the LaunchPad is 9600 bps, though 2400
appears common (if the LFXT1 is used more directly.) This
arrangement permits the maximum 9600 bps rate with
appropriate code to go along with it.

I have that code, as well. If anyone needs something to run
a DCO FLL cpu rate while operating the virtual COM port at
9600 with better than 1% variation around the accuracy value
of the crystal.
; ---------------
; CRUCIAL PROGRAM-CONTROL INPUTS
; ---------------
; The bit-per-second rate required by the TxD pin is
; determined by prior design of the Launchpad system
; and is 9600 bps. But it is specified as a param
; here to allow exploration of other rates (and just
; in case it changes in some fashion in later rev's
; where the USB drivers on both sides permit a
; hosted application on the PC to open up the
; virtual COM port at some specified rate that gets
; passed along and controls the desired rate here.)
; Also, it is always possible for someone to replace
; the 32.768kHz crystal with a different value, so
; another parameter is permitted here for that case.
; Finally, a preferred MCLK value is allowed because
; there may "better" rates for it that others may
; wish to test.

RS232_RATE DEFINE (9600)
LFXT1_FREQ DEFINE (32768)
PREFERRED_MCLK_FREQ DEFINE (16000000)

; ---------------
; CRUCIAL PROGRAM-CONTROL INPUTS
; ---------------
; The above control parameters may be used to
; compute the actual number of clocks required for
; each RS-232 1/2-bit time (necessary for generating
; the rising and falling clock edges used during
; transmission) and multiplier for the DCO vs LFXT1
; FLL (frequency-locked loop.) These computed
; values are then locked in place as SETPOINT and
; TXD_TIME and used by the code.
;
; A simple validation is also performed at compile-
; time. If an incongruency between the above
; control parameters is discovered, the code will
; simply not compile and an error message will be
; emitted, instead.

MCLK_TARGET VAR (PREFERRED_MCLK_FREQ)
REPT 6
SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
TXD_TARGET VAR (ACTUAL_MCLK/(2*RS232_RATE))
MCLK_TARGET VAR (TXD_TARGET*2*RS232_RATE)
ENDR
ACTUAL_RATE VAR (MCLK_ACTUAL/(2*TXD_TARGET))

LIMIT ACTUAL_RATE, RS232_RATE, RS232_RATE, "ERROR!"

SETPOINT EQU (SETP_TARGET)
TXD_TIME EQU (TXD_TARGET)
MCLK_ACTUAL EQU (ACTUAL_MCLK)

These last three values are used in the code. Actually, just
SETPOINT and TXD_TIME. MCLK_ACTUAL is produced because I
like to see it in the listing file with the computed value
stated in clear terms.

Jon

Beginning Microcontrollers with the MSP430

On Fri, 27 May 2011 17:32:23 -0700, you wrote:

> ; each RS-232 1/2-bit time (necessary for generating
> ; the rising and falling clock edges used during
> ; transmission) and multiplier for the DCO vs LFXT1

Just for clarification, I happen to generate an internal
clock for driving an external device, which is part of why I
need a 2X clock rate for the RS232. The algorithm might be
easily adjusted for a 1X event clock in cases where such an
external clock isn't generated and only RS232 bit-timing is
required. Replace (2*RS232_RATE) with (RS232_RATE) in such a
case.

Jon
Jon,
One question:
When evaluating your equations I can find:
SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
means
ACTUAK_MCLK = (MCLK_TARGET / (LFXT1_FREQ/8)) * (LFXT1_FREQ/8)
and this means
ACTUAL_MCLK = MCLK_TARGET
.
.
and then:
.
TXD_TARGET VAR (ACTUAL_MCLK/(2*RS232_RATE))
MCLK_TARGET VAR (TXD_TARGET*2*RS232_RATE)
also means, again,
MCLK_TARGET = ACTUAL_MCLK
Are these interations with the purpouse of reduce the calculated
value due to losses in the integer math?
If so this kind of math evaluation is very interesting to learn. I
miss this study...
.
Kind regards,
Augusto
On Sex 27/05/11 21:32 , Jon Kirwan j...@infinitefactors.org sent:
I wanted to automatically generate certain timing values used
by LaunchPad-targeted code. The purpose is to operate a
software FLL on the MSP430G22x1 cpu, which requires one
integer multiplier, and to properly operate the asynchronous
serial port communications (to the virtual COM port on a PC)
with another integer divisor. The way I chose to run the
serial communications was to divide SMCLK/MCLK down to twice
the serial port rate. That fact explains the (2*RS232_RATE)
you will see in the example code below.
Because better precision is achieved this way, LFXT1 is
divided down by 8 in the code so that the larger possible
values of SMCLK may be counted. The algorithm below assumes
this divide-by-8 case as shown in the (LFXT1_FREQ/8) you will
also see in the example code below.
So SMCLK/MCLK must be an integer multiple of some divided-
down LFXT1 rate (ACLK) and it must *also* be an integer
multiple of two times the serial rate. The result is two
very useful integer count values... one used as a multiplier
for the FLL, one used as a divider from that to get the
asynchronous serial clock.
(It was in developing this, that I encountered the assembler
bug.)
I don't know if anyone else can use this, but I figured I'd
dump it out there. It works quite nicely on my application.
And I've tested various variations and had the application
run just fine (and operate the DCO correctly, as well) for a
variety of attempted values.
Just something that may help those doing LaunchPad hobby
stuff. No copyright is retained here (as if I had much
control over that.) And of course, it is offered without
warranty, too!
(The REPT 6 used below usually isn't required as it settles
long before 6 iterations. So the 6 is non-critical. Use 2
or 3, if comfortable. I just set the 6, arbitrarily.)
This is for a Timer A2 device. I believe the maximum rate
that can be used with the LaunchPad is 9600 bps, though 2400
appears common (if the LFXT1 is used more directly.) This
arrangement permits the maximum 9600 bps rate with
appropriate code to go along with it.
I have that code, as well. If anyone needs something to run
a DCO FLL cpu rate while operating the virtual COM port at
9600 with better than 1% variation around the accuracy value
of the crystal.
; ---------------
; CRUCIAL PROGRAM-CONTROL INPUTS
; ---------------
; The bit-per-second rate required by the TxD pin is
; determined by prior design of the Launchpad system
; and is 9600 bps. But it is specified as a param
; here to allow exploration of other rates (and just
; in case it changes in some fashion in later rev's
; where the USB drivers on both sides permit a
; hosted application on the PC to open up the
; virtual COM port at some specified rate that gets
; passed along and controls the desired rate here.)
; Also, it is always possible for someone to replace
; the 32.768kHz crystal with a different value, so
; another parameter is permitted here for that case.
; Finally, a preferred MCLK value is allowed because
; there may "better" rates for it that others may
; wish to test.
RS232_RATE DEFINE (9600)
LFXT1_FREQ DEFINE (32768)
PREFERRED_MCLK_FREQ DEFINE (16000000)
; ---------------
; CRUCIAL PROGRAM-CONTROL INPUTS
; ---------------
; The above control parameters may be used to
; compute the actual number of clocks required for
; each RS-232 1/2-bit time (necessary for generating
; the rising and falling clock edges used during
; transmission) and multiplier for the DCO vs LFXT1
; FLL (frequency-locked loop.) These computed
; values are then locked in place as SETPOINT and
; TXD_TIME and used by the code.
;
; A simple validation is also performed at compile-
; time. If an incongruency between the above
; control parameters is discovered, the code will
; simply not compile and an error message will be
; emitted, instead.
MCLK_TARGET VAR (PREFERRED_MCLK_FREQ)
REPT 6
SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
TXD_TARGET VAR (ACTUAL_MCLK/(2*RS232_RATE))
MCLK_TARGET VAR (TXD_TARGET*2*RS232_RATE)
ENDR
ACTUAL_RATE VAR (MCLK_ACTUAL/(2*TXD_TARGET))
LIMIT ACTUAL_RATE, RS232_RATE, RS232_RATE, "ERROR!"
SETPOINT EQU (SETP_TARGET)
TXD_TIME EQU (TXD_TARGET)
MCLK_ACTUAL EQU (ACTUAL_MCLK)
These last three values are used in the code. Actually, just
SETPOINT and TXD_TIME. MCLK_ACTUAL is produced because I
like to see it in the listing file with the computed value
stated in clear terms.
Jon



On Sat, 28 May 2011 01:27:01 +0000, you wrote:

> Jon,
> One question:
> When evaluating your equations I can find:
> SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
> ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
> means
> ACTUAK_MCLK = (MCLK_TARGET / (LFXT1_FREQ/8)) * (LFXT1_FREQ/8)
> and this means
> ACTUAL_MCLK = MCLK_TARGET
> .
> .
> and then:
> .
> TXD_TARGET VAR (ACTUAL_MCLK/(2*RS232_RATE))
> MCLK_TARGET VAR (TXD_TARGET*2*RS232_RATE)
> also means, again,
> MCLK_TARGET = ACTUAL_MCLK
> Are these interations with the purpouse of reduce the calculated
> value due to losses in the integer math?
> If so this kind of math evaluation is very interesting to learn. I
> miss this study...
> .
> Kind regards,
> Augusto

Pretty much, yes. The point here is to take advantage of
truncations that IAR performs. No FP math here.

For example:

SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))

The first line truncates away fractional parts. The second
line takes this value and multiplies it back up to a new,
slightly smaller (perhaps) value. Iteration solves it.

Works very nicely.

I suppose the "miss this study" part is a piece of why I wind
up finding bugs in compiler tools so often. I press them a
bit more than many.

In this case, the interesting thing about the resulting
application is that I just specify the desired RS232 rate,
the crystal freq, and some rough idea of where I'd like the
cpu running (MCLK), and it is simplicity itself to
reconfigure things. The assembler does all the math work.

For example: The DCO will be operated near 16MHz, but
synchronized to LFXT1 for the accuracy desired for operating
the asynchronous serial pin, TxD, which is then used to send
ASCII characters into the PC at the rate of 9600, which
itself cannot be handled by the LFXT1 by itself (we need the
DCO to crank things up a bit with a software FLL on the value
line part.) With a desired data rate of 9600 bps, SMCLK
(driven by the DCO) should be some integer multiple of 9600,
so that it divides down evenly. Call this integer, M. The
LFXT1 crystal may be divided down by one of these factors,
1/2/4/8, to provide ACLK. ACLK (via CCI0B) will cause a
capture of a timer counter used to count SMCLK cycles per
ACLK event. So it would be convenient if SMCLK were chosen
so that SMCLK/ACLK is an integer value. Call the integer,
SETPOINT. It follows that SMCLK=SETPOINT*ACLK, SMCLK=M*9600
and thus M*9600=SETPOINT*ACLK. To get the largest value for
SETPOINT the smallest possible value for ACLK is used. So
divide LFXT1 by 8, giving 4096 for ACLK. The GCD of 9600 and
4096 is 128. Therefore M*75=SETPOINT*32. In order for this
equation to work with integers only, M must include 32 as a
factor. So the minimum rate for SMCLK is 32*9600 or
307.2kHz. But to operate near 16MHz, find the nearest
integer for 16MHz/307.2kHz and get 52. So 52*32*9600 gives
an operating SMCLK of 15.9744MHz and a SETPOINT of 3900.

The assembler's compile-time algorithm I posted up will
actually compute 3900 as the FLL count to target and the
value of 832 (1/2 of 1664) for the half-bit time of the 9600
bps communications rate. Everything evenly divides out and
the resulting MCLK is that 15.9744MHz rate, close to the
desired 16MHz, as provided.

The programmer doesn't have to lose any hair. ;)

And the FLL I use processes things with a PI loop (16 bit
integrator included) so that the LONG TERM accuracy (not
merely short term) is maintained to a finer precision than
would be possible with the usual code you see from TI. Nice.

Jon

Yes, it works nicelly and the "miss this study" was exactly on the
math to find the correction values by using the resolution loss in the
integer calculations.
Like this kind of solution.
-Augusto
On Sáb 28/05/11 07:17 , Jon Kirwan j...@infinitefactors.org sent:
On Sat, 28 May 2011 01:27:01 +0000, you wrote:
> Jon,
> One question:
> When evaluating your equations I can find:
> SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
> ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
> means
> ACTUAK_MCLK = (MCLK_TARGET / (LFXT1_FREQ/8)) * (LFXT1_FREQ/8)
> and this means
> ACTUAL_MCLK = MCLK_TARGET
> .
> .
> and then:
> .
> TXD_TARGET VAR (ACTUAL_MCLK/(2*RS232_RATE))
> MCLK_TARGET VAR (TXD_TARGET*2*RS232_RATE)
> also means, again,
> MCLK_TARGET = ACTUAL_MCLK
> Are these interations with the purpouse of reduce the calculated
> value due to losses in the integer math?
> If so this kind of math evaluation is very interesting to learn. I
> miss this study...
> .
> Kind regards,
> Augusto
Pretty much, yes. The point here is to take advantage of
truncations that IAR performs. No FP math here.
For example:
SETP_TARGET VAR (MCLK_TARGET/(LFXT1_FREQ/8))
ACTUAL_MCLK VAR (SETP_TARGET*(LFXT1_FREQ/8))
The first line truncates away fractional parts. The second
line takes this value and multiplies it back up to a new,
slightly smaller (perhaps) value. Iteration solves it.
Works very nicely.
I suppose the "miss this study" part is a piece of why I wind
up finding bugs in compiler tools so often. I press them a
bit more than many.
In this case, the interesting thing about the resulting
application is that I just specify the desired RS232 rate,
the crystal freq, and some rough idea of where I'd like the
cpu running (MCLK), and it is simplicity itself to
reconfigure things. The assembler does all the math work.
For example: The DCO will be operated near 16MHz, but
synchronized to LFXT1 for the accuracy desired for operating
the asynchronous serial pin, TxD, which is then used to send
ASCII characters into the PC at the rate of 9600, which
itself cannot be handled by the LFXT1 by itself (we need the
DCO to crank things up a bit with a software FLL on the value
line part.) With a desired data rate of 9600 bps, SMCLK
(driven by the DCO) should be some integer multiple of 9600,
so that it divides down evenly. Call this integer, M. The
LFXT1 crystal may be divided down by one of these factors,
1/2/4/8, to provide ACLK. ACLK (via CCI0B) will cause a
capture of a timer counter used to count SMCLK cycles per
ACLK event. So it would be convenient if SMCLK were chosen
so that SMCLK/ACLK is an integer value. Call the integer,
SETPOINT. It follows that SMCLK=SETPOINT*ACLK, SMCLK=M*9600
and thus M*9600=SETPOINT*ACLK. To get the largest value for
SETPOINT the smallest possible value for ACLK is used. So
divide LFXT1 by 8, giving 4096 for ACLK. The GCD of 9600 and
4096 is 128. Therefore M*75=SETPOINT*32. In order for this
equation to work with integers only, M must include 32 as a
factor. So the minimum rate for SMCLK is 32*9600 or
307.2kHz. But to operate near 16MHz, find the nearest
integer for 16MHz/307.2kHz and get 52. So 52*32*9600 gives
an operating SMCLK of 15.9744MHz and a SETPOINT of 3900.
The assembler's compile-time algorithm I posted up will
actually compute 3900 as the FLL count to target and the
value of 832 (1/2 of 1664) for the half-bit time of the 9600
bps communications rate. Everything evenly divides out and
the resulting MCLK is that 15.9744MHz rate, close to the
desired 16MHz, as provided.
The programmer doesn't have to lose any hair. ;)
And the FLL I use processes things with a PI loop (16 bit
integrator included) so that the LONG TERM accuracy (not
merely short term) is maintained to a finer precision than
would be possible with the usual code you see from TI. Nice.
Jon



On Sat, 28 May 2011 13:08:12 +0000, Augusto wrote:

> Yes, it works nicelly and the "miss this study" was exactly on the
>math to find the correction values by using the resolution loss in the
>integer calculations.
> Like this kind of solution.

I guess I'm a little taken aback, because it's from crystal
clear method that I didn't take closer note about until you
wrote this way about it. I did figure it might be useful for
others, which is why I posted it. But it never did occur to
me that it was anything more than that. I guess I figured
everyone does this, without thinking, as I do. Posting it
was more about passing along a useful snippet. Not about
teaching some methodology. It was 'obvious,' I thought. I
am glad, of course, that you like it!

But if you are interested in these kinds of things, there is
a very nice book that discusses it more directly than most.
It's called Concrete Mathematics. Donald Knuth and others
wrote it and it is excellent.

It's not what taught me this. What I did here is something
I've done for more than 35 years. Long enough that I can no
longer recall where I picked it up, or if it was something I
learned elsewhere and applied on my own in a slightly
creative way a very long time ago and just used over the
years. But Concrete Mathematics is the kind of book that
covers things like this better than others I'm aware of.

There are books on numerical methods and interative
solutions, I suppose. I've read some over the years, but
can't recall any that stand out like Concrete Mathematics
does in my mind for this kind of thing. Lots concentrated
into one place, there.

Jon

P.S. Convergence and iterative solution methods like this
are found nearly everywhere, which is why I was taken
pleasantly aback by your comments here. If you have some
more questions, though, please feel free to ask about them. I
like this area and love to discuss both theory and detailed
application with others.