mbed library sources
Dependents: frdm_kl05z_gpio_test
Fork of mbed-src by
Diff: targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c
- Revision:
- 51:7838415c99e7
- Parent:
- 40:5fa4b7c54c1d
- Child:
- 64:7b352733b00a
diff -r b08ceb75017d -r 7838415c99e7 targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c --- 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; } } }