#include "imxrt.h"
#include "core_pins.h"
#include "debug/printf.h"
struct pwm_pin_info_struct {
uint8_t type; // 0=no pwm, 1=flexpwm, 2=quad
uint8_t module; // 0-3, 0-3
uint8_t channel; // 0=X, 1=A, 2=B
uint8_t muxval; //
};
#define M(a, b) ((((a) - 1) << 4) | (b))
#if defined(__IMXRT1062__)
const struct pwm_pin_info_struct pwm_pin_info[] = {
{1, M(1, 1), 0, 4}, // FlexPWM1_1_X 0 // AD_B0_03
{1, M(1, 0), 0, 4}, // FlexPWM1_0_X 1 // AD_B0_02
{1, M(4, 2), 1, 1}, // FlexPWM4_2_A 2 // EMC_04
{1, M(4, 2), 2, 1}, // FlexPWM4_2_B 3 // EMC_05
{1, M(2, 0), 1, 1}, // FlexPWM2_0_A 4 // EMC_06
{1, M(2, 1), 1, 1}, // FlexPWM2_1_A 5 // EMC_08
{1, M(2, 2), 1, 2}, // FlexPWM2_2_A 6 // B0_10
{1, M(1, 3), 2, 6}, // FlexPWM1_3_B 7 // B1_01
{1, M(1, 3), 1, 6}, // FlexPWM1_3_A 8 // B1_00
{1, M(2, 2), 2, 2}, // FlexPWM2_2_B 9 // B0_11
{2, M(1, 0), 0, 1}, // QuadTimer1_0 10 // B0_00
{2, M(1, 2), 0, 1}, // QuadTimer1_2 11 // B0_02
{2, M(1, 1), 0, 1}, // QuadTimer1_1 12 // B0_01
{2, M(2, 0), 0, 1}, // QuadTimer2_0 13 // B0_03
{2, M(3, 2), 0, 1}, // QuadTimer3_2 14 // AD_B1_02
{2, M(3, 3), 0, 1}, // QuadTimer3_3 15 // AD_B1_03
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{2, M(3, 1), 0, 1}, // QuadTimer3_1 18 // AD_B1_01
{2, M(3, 0), 0, 1}, // QuadTimer3_0 19 // AD_B1_00
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{1, M(4, 0), 1, 1}, // FlexPWM4_0_A 22 // AD_B1_08
{1, M(4, 1), 1, 1}, // FlexPWM4_1_A 23 // AD_B1_09
{1, M(1, 2), 0, 4}, // FlexPWM1_2_X 24 // AD_B0_12
{1, M(1, 3), 0, 4}, // FlexPWM1_3_X 25 // AD_B0_13
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{1, M(3, 1), 2, 1}, // FlexPWM3_1_B 28 // EMC_32
{1, M(3, 1), 1, 1}, // FlexPWM3_1_A 29 // EMC_31
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{1, M(2, 0), 2, 1}, // FlexPWM2_0_B 33 // EMC_07
#ifdef ARDUINO_TEENSY41
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{1, M(2, 3), 1, 6}, // FlexPWM2_3_A 36 // B1_00
{1, M(2, 3), 2, 6}, // FlexPWM2_3_B 37 // B1_01
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{0, M(1, 0), 0, 0},
{1, M(1, 1), 2, 1}, // FlexPWM1_1_B 42 // SD_B0_03
{1, M(1, 1), 1, 1}, // FlexPWM1_1_A 43 // SD_B0_02
{1, M(1, 0), 2, 1}, // FlexPWM1_0_B 44 // SD_B0_01
{1, M(1, 0), 1, 1}, // FlexPWM1_0_A 45 // SD_B0_00
{1, M(1, 2), 2, 1}, // FlexPWM1_2_B 46 // SD_B0_05
{1, M(1, 2), 1, 1}, // FlexPWM1_2_A 47 // SD_B0_04
{0, M(1, 0), 0, 0}, // duplicate FlexPWM1_0_B
{0, M(1, 0), 0, 0}, // duplicate FlexPWM1_2_A
{0, M(1, 0), 0, 0}, // duplicate FlexPWM1_2_B
{1, M(3, 3), 2, 1}, // FlexPWM3_3_B 51 // EMC_22
{0, M(1, 0), 0, 0}, // duplicate FlexPWM1_1_B
{0, M(1, 0), 0, 0}, // duplicate FlexPWM1_1_A
{1, M(3, 0), 1, 1}, // FlexPWM3_0_A 54 // EMC_29
#endif
};
#endif // __IMXRT1062__
void setup()
{
analogWriteResolution(9);
analogWriteFrequency(6, 195312);
analogWrite(6, 50);
MyanalogWriteFrequencyPS(9, 195312,100);
analogWrite(9, 50);
}
void MyanalogWriteFrequencyPS(uint8_t pin, float mfrequency, int phaseshift)
{
const struct pwm_pin_info_struct *info;
if (pin >= CORE_NUM_DIGITAL) return;
//printf("analogWriteFrequency, pin %d, freq %d\n", pin, (int)frequency);
info = pwm_pin_info + pin;
if (info->type == 1) {
// FlexPWM pin
IMXRT_FLEXPWM_t *flexpwm;
switch ((info->module >> 4) & 3) {
case 0: flexpwm = &IMXRT_FLEXPWM1; break;
case 1: flexpwm = &IMXRT_FLEXPWM2; break;
case 2: flexpwm = &IMXRT_FLEXPWM3; break;
default: flexpwm = &IMXRT_FLEXPWM4;
}
MyflexpwmFrequencyPS(flexpwm, info->module & 0x03, info->channel, mfrequency, phaseshift);
} else if (info->type == 2) {
// QuadTimer pin
//ignore
}
}
void MyflexpwmFrequencyPS(IMXRT_FLEXPWM_t *p, unsigned int submodule, uint8_t channel, float mfrequency, int phaseshift)
{
uint16_t mask = 1 << submodule;
uint32_t olddiv = p->SM[submodule].VAL1;
uint32_t newdiv = (uint32_t)((float)F_BUS_ACTUAL / mfrequency + 0.5f);
uint32_t prescale = 0;
//printf(" div=%lu\n", newdiv);
while (newdiv > 65535 && prescale < 7) {
newdiv = newdiv >> 1;
prescale = prescale + 1;
}
if (newdiv > 65535) {
newdiv = 65535;
} else if (newdiv < 2) {
newdiv = 2;
}
//printf(" div=%lu, scale=%lu\n", newdiv, prescale);
p->MCTRL |= FLEXPWM_MCTRL_CLDOK(mask);
p->SM[submodule].CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_PRSC(prescale);
p->SM[submodule].VAL1 = newdiv - 1;
p->SM[submodule].VAL2 = ((p->SM[submodule].VAL2 + phaseshift) * newdiv) / olddiv; //offset from start at 0
p->SM[submodule].VAL0 = (p->SM[submodule].VAL0 * newdiv) / olddiv;
p->SM[submodule].VAL3 = ((p->SM[submodule].VAL3 + phaseshift) * newdiv) / olddiv;
p->SM[submodule].VAL5 = (p->SM[submodule].VAL5 * newdiv) / olddiv;
p->MCTRL |= FLEXPWM_MCTRL_LDOK(mask);
}
void loop()
{
}