00001
00040 #include "pwm_at91.h"
00041 #include "hw/pwm_map.h"
00042 #include <hw/hw_cpufreq.h>
00043 #include "cfg/cfg_pwm.h"
00044
00045
00046 #define LOG_LEVEL PWM_LOG_LEVEL
00047 #define LOG_FORMAT PWM_LOG_FORMAT
00048 #include <cfg/log.h>
00049
00050 #include <cfg/macros.h>
00051 #include <cfg/debug.h>
00052
00053 #include <io/arm.h>
00054
00055
00061 static PwmChannel pwm_map[PWM_CNT] =
00062 {
00063 {
00064 .duty_zero = false,
00065 .pol = false,
00066 .pwm_pin = BV(PWM0),
00067 .mode_reg = &PWM_CMR0,
00068 .duty_reg = &PWM_CDTY0,
00069 .period_reg = &PWM_CPRD0,
00070 .update_reg = &PWM_CUPD0,
00071 },
00072 {
00073 .duty_zero = false,
00074 .pol = false,
00075 .pwm_pin = BV(PWM1),
00076 .mode_reg = &PWM_CMR1,
00077 .duty_reg = &PWM_CDTY1,
00078 .period_reg = &PWM_CPRD1,
00079 .update_reg = &PWM_CUPD1,
00080 },
00081 {
00082 .duty_zero = false,
00083 .pol = false,
00084 .pwm_pin = BV(PWM2),
00085 .mode_reg = &PWM_CMR2,
00086 .duty_reg = &PWM_CDTY2,
00087 .period_reg = &PWM_CPRD2,
00088 .update_reg = &PWM_CUPD2,
00089 },
00090 {
00091 .duty_zero = false,
00092 .pol = false,
00093 .pwm_pin = BV(PWM3),
00094 .mode_reg = &PWM_CMR3,
00095 .duty_reg = &PWM_CDTY3,
00096 .period_reg = &PWM_CPRD3,
00097 .update_reg = &PWM_CUPD3,
00098 }
00099 };
00100
00101
00107 pwm_period_t pwm_hw_getPeriod(PwmDev dev)
00108 {
00109 return *pwm_map[dev].period_reg;
00110 }
00111
00117 void pwm_hw_setFrequency(PwmDev dev, uint32_t freq)
00118 {
00119 uint32_t period = 0;
00120
00121 for(int i = 0; i <= PWM_HW_MAX_PRESCALER_STEP; i++)
00122 {
00123 period = CPU_FREQ / (BV(i) * freq);
00124 LOG_INFO("period[%ld], prescale[%d]\n", period, i);
00125 if ((period < PWM_HW_MAX_PERIOD) && (period != 0))
00126 {
00127
00128 *pwm_map[dev].mode_reg &= ~PWM_CPRE_MCK_MASK;
00129 *pwm_map[dev].mode_reg |= i;
00130
00131 *pwm_map[dev].period_reg = period;
00132 break;
00133 }
00134 }
00135
00136 LOG_INFO("PWM ch[%d] period[%ld]\n", dev, period);
00137 }
00138
00144 void pwm_hw_setDutyUnlock(PwmDev dev, uint16_t duty)
00145 {
00146 ASSERT(duty <= (uint16_t)*pwm_map[dev].period_reg);
00147
00148
00149
00150
00151
00152
00153 if (pwm_map[dev].pol)
00154 {
00155 duty = (uint16_t)*pwm_map[dev].period_reg - duty;
00156 LOG_INFO("Inverted duty[%d], pol[%d]\n", duty, pwm_map[dev].pol);
00157 }
00158
00159
00160
00161
00162
00163 if (!duty)
00164 {
00165 PWM_PIO_CODR = pwm_map[dev].pwm_pin;
00166 PWM_PIO_PER = pwm_map[dev].pwm_pin;
00167 pwm_map[dev].duty_zero = true;
00168 }
00169 else
00170 {
00171 PWM_PIO_PDR = pwm_map[dev].pwm_pin;
00172 PWM_PIO_ABSR = pwm_map[dev].pwm_pin;
00173
00174 *pwm_map[dev].update_reg = duty;
00175 pwm_map[dev].duty_zero = false;
00176 }
00177
00178 PWM_ENA = BV(dev);
00179 LOG_INFO("PWM ch[%d] duty[%d], period[%ld]\n", dev, duty, *pwm_map[dev].period_reg);
00180 }
00181
00182
00186 void pwm_hw_enable(PwmDev dev)
00187 {
00188 if (!pwm_map[dev].duty_zero)
00189 {
00190 PWM_PIO_PDR = pwm_map[dev].pwm_pin;
00191 PWM_PIO_ABSR = pwm_map[dev].pwm_pin;
00192 }
00193 }
00194
00198 void pwm_hw_disable(PwmDev dev)
00199 {
00200 PWM_PIO_PER = pwm_map[dev].pwm_pin;
00201 }
00202
00206 void pwm_hw_setPolarity(PwmDev dev, bool pol)
00207 {
00208 pwm_map[dev].pol = pol;
00209 LOG_INFO("Set pol[%d]\n", pwm_map[dev].pol);
00210 }
00211
00215 void pwm_hw_init(void)
00216 {
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 PWM_PIO_CODR = BV(PWM0) | BV(PWM1) | BV(PWM2) | BV(PWM3);
00228 PWM_PIO_OER = BV(PWM0) | BV(PWM1) | BV(PWM2) | BV(PWM3);
00229 PWM_PIO_PDR = BV(PWM0) | BV(PWM1) | BV(PWM2) | BV(PWM3);
00230 PWM_PIO_ABSR = BV(PWM0) | BV(PWM1) | BV(PWM2) | BV(PWM3);
00231 PMC_PCER |= BV(PWMC_ID);
00232
00233
00234 PWM_DIS = 0xFFFFFFFF;
00235
00236 PWM_MR = 0;
00237
00238
00239
00240
00241
00242
00243
00244 for (int ch = 0; ch < PWM_CNT; ch++)
00245 {
00246 *pwm_map[ch].mode_reg = 0;
00247 *pwm_map[ch].mode_reg = BV(PWM_CPOL);
00248 }
00249
00250 }
00251