Removed hardcoded frequencies, replaced by automatically calculated

ADC frequency 1.5MHz -> 6MHz (if possible, otherwise it tries as close
to, but less than 6MHz)
pwm tries to get its clock as close as possible to 1MHz, but not lower
than 1MHz
pull/140/head
Sissors 2014-01-10 21:45:26 +01:00
parent 7df2622a76
commit eedce209c5
5 changed files with 36 additions and 22 deletions

View File

@ -19,6 +19,8 @@
#include "pinmap.h" #include "pinmap.h"
#include "error.h" #include "error.h"
#define MAX_FADC 6000000
static const PinMap PinMap_ADC[] = { static const PinMap PinMap_ADC[] = {
{PTE20, ADC0_SE0, 0}, {PTE20, ADC0_SE0, 0},
{PTE22, ADC0_SE3, 0}, {PTE22, ADC0_SE3, 0},
@ -55,13 +57,23 @@ void analogin_init(analogin_t *obj, PinName pin) {
cfg2_muxsel = 0; cfg2_muxsel = 0;
} }
// bus clk
uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
uint32_t clkdiv;
for (clkdiv = 0; clkdiv < 4; clkdiv++) {
if ((PCLK >> clkdiv) <= MAX_FADC)
break;
}
if (clkdiv == 4) //Set max div
clkdiv = 0x7;
ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT)); ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT));
ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration
| ADC_CFG1_ADIV(3) // Clock Divide Select: (Input Clock)/8 | ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select: (Input Clock)/8
| ADC_CFG1_ADLSMP_MASK // Long Sample Time | ADC_CFG1_ADLSMP_MASK // Long Sample Time
| ADC_CFG1_MODE(3) // (16)bits Resolution | ADC_CFG1_MODE(3) // (16)bits Resolution
| ADC_CFG1_ADICLK(1); // Input Clock: (Bus Clock)/2 | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock: (Bus Clock)/2
ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels
| ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable | ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable

View File

@ -206,7 +206,7 @@ void i2c_frequency(i2c_t *obj, int hz) {
uint32_t ref = 0; uint32_t ref = 0;
uint8_t i, j; uint8_t i, j;
// bus clk // bus clk
uint32_t PCLK = 24000000u; uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
uint32_t pulse = PCLK / (hz * 2); uint32_t pulse = PCLK / (hz * 2);
// we look for the values that minimize the error // we look for the values that minimize the error

View File

@ -64,7 +64,7 @@ static const PinMap PinMap_PWM[] = {
{NC , NC , 0} {NC , NC , 0}
}; };
#define PWM_CLOCK_MHZ (0.75) // (48)MHz / 64 = (0.75)MHz static float pwm_clock;
void pwmout_init(pwmout_t* obj, PinName pin) { void pwmout_init(pwmout_t* obj, PinName pin) {
// determine the channel // determine the channel
@ -72,6 +72,17 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
if (pwm == (PWMName)NC) if (pwm == (PWMName)NC)
error("PwmOut pin mapping failed"); error("PwmOut pin mapping failed");
uint32_t clkdiv = 0;
float clkval = SystemCoreClock / 1000000.0f;
while (clkval > 1) {
clkdiv++;
clkval /= 2.0;
if (clkdiv == 7)
break;
}
pwm_clock = clkval;
unsigned int port = (unsigned int)pin >> PORT_SHIFT; unsigned int port = (unsigned int)pin >> PORT_SHIFT;
unsigned int tpm_n = (pwm >> TPM_SHIFT); unsigned int tpm_n = (pwm >> TPM_SHIFT);
unsigned int ch_n = (pwm & 0xFF); unsigned int ch_n = (pwm & 0xFF);
@ -125,7 +136,7 @@ void pwmout_period_ms(pwmout_t* obj, int ms) {
// Set the PWM period, keeping the duty cycle the same. // Set the PWM period, keeping the duty cycle the same.
void pwmout_period_us(pwmout_t* obj, int us) { void pwmout_period_us(pwmout_t* obj, int us) {
float dc = pwmout_read(obj); float dc = pwmout_read(obj);
*obj->MOD = PWM_CLOCK_MHZ * us; *obj->MOD = (uint32_t)(pwm_clock * (float)us);
pwmout_write(obj, dc); pwmout_write(obj, dc);
} }
@ -138,5 +149,5 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
} }
void pwmout_pulsewidth_us(pwmout_t* obj, int us) { void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
*obj->CnV = PWM_CLOCK_MHZ * us; *obj->CnV = (uint32_t)(pwm_clock * (float)us);
} }

View File

@ -111,16 +111,6 @@ void serial_free(serial_t *obj) {
// serial_baud // serial_baud
// //
// set the baud rate, taking in to account the current SystemFrequency // set the baud rate, taking in to account the current SystemFrequency
//
// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
// baud rate. The formula is:
//
// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
// where:
// 1 < MulVal <= 15
// 0 <= DivAddVal < 14
// DivAddVal < MulVal
//
void serial_baud(serial_t *obj, int baudrate) { void serial_baud(serial_t *obj, int baudrate) {
// save C2 state // save C2 state
@ -130,7 +120,7 @@ void serial_baud(serial_t *obj, int baudrate) {
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK); obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
// [TODO] not hardcode this value // [TODO] not hardcode this value
uint32_t PCLK = (obj->uart == UART0) ? 48000000u : 24000000u; uint32_t PCLK = (obj->uart == UART0) ? SystemCoreClock : SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
// First we check to see if the basic divide with no DivAddVal/MulVal // First we check to see if the basic divide with no DivAddVal/MulVal
// ratio gives us an integer result. If it does, we set DivAddVal = 0, // ratio gives us an integer result. If it does, we set DivAddVal = 0,

View File

@ -43,7 +43,8 @@ static void pit_init(void) {
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1 PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1
// Use channel 0 as a prescaler for channel 1 // Use channel 0 as a prescaler for channel 1
PIT->CHANNEL[0].LDVAL = 23; uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
PIT->CHANNEL[0].LDVAL = PCLK / 1000000 - 1;
PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts
} }