mirror of https://github.com/ARMmbed/mbed-os.git
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 1MHzpull/140/head
parent
7df2622a76
commit
eedce209c5
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue