mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Revision:
51:7838415c99e7
Parent:
40:5fa4b7c54c1d
Child:
64:7b352733b00a
--- a/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c	Tue Nov 26 15:30:05 2013 +0000
+++ b/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c	Mon Dec 02 10:00:04 2013 +0000
@@ -157,22 +157,47 @@
     uint16_t dlv;
     uint8_t mv, dav;
     if ((PCLK % (16 * baudrate)) != 0) {     // Checking for zero remainder
-        float err_best = (float) baudrate;
-        uint16_t dlmax = DL;
-        for ( dlv = (dlmax/2); (dlv <= dlmax) && !hit; dlv++) {
-            for ( mv = 1; mv <= 15; mv++) {
-                for ( dav = 1; dav < mv; dav++) {
-                    float ratio = 1.0f + ((float) dav / (float) mv);
-                    float calcbaud = (float)PCLK / (16.0f * (float) dlv * ratio);
-                    float err = fabs(((float) baudrate - calcbaud) / (float) baudrate);
-                    if (err < err_best) {
-                        DL = dlv;
-                        DivAddVal = dav;
-                        MulVal = mv;
-                        err_best = err;
-                        if (err < 0.001f) {
-                            hit = 1;
-                        }
+        int err_best = baudrate, b;
+        for (mv = 1; mv < 16 && !hit; mv++)
+        {
+            for (dav = 0; dav < mv; dav++)
+            {
+                // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
+                // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
+                // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
+                // for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision
+                // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
+
+                if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
+                    dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
+                else // 2 bits headroom, use more precision
+                    dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
+
+                // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
+                if (dlv == 0)
+                    dlv = 1;
+
+                // datasheet says if dav > 0 then DL must be >= 2
+                if ((dav > 0) && (dlv < 2))
+                    dlv = 2;
+
+                // integer rearrangement of the baudrate equation (with rounding)
+                b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
+
+                // check to see how we went
+                b = abs(b - baudrate);
+                if (b < err_best)
+                {
+                    err_best  = b;
+
+                    DL        = dlv;
+                    MulVal    = mv;
+                    DivAddVal = dav;
+
+                    if (b == baudrate)
+                    {
+                        hit = 1;
+                        break;
                     }
                 }
             }