|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #include "imxrt.h"
- #include "core_pins.h"
- #include "debug/printf.h"
-
-
- struct pwm_pin_info_struct {
- uint8_t type;
- uint8_t module;
- uint8_t channel;
- uint8_t muxval;
- };
-
- uint8_t analog_write_res = 8;
-
- #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},
- {1, M(1, 0), 0, 4},
- {1, M(4, 2), 1, 1},
- {1, M(4, 2), 2, 1},
- {1, M(2, 0), 1, 1},
- {1, M(2, 1), 1, 1},
- {1, M(2, 2), 1, 2},
- {1, M(1, 3), 2, 6},
- {1, M(1, 3), 1, 6},
- {1, M(2, 2), 2, 2},
- {2, M(1, 0), 0, 1},
- {2, M(1, 2), 0, 1},
- {2, M(1, 1), 0, 1},
- {2, M(2, 0), 0, 1},
- {2, M(3, 2), 0, 1},
- {2, M(3, 3), 0, 1},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {2, M(3, 1), 0, 1},
- {2, M(3, 0), 0, 1},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {1, M(4, 0), 1, 1},
- {1, M(4, 1), 1, 1},
- {1, M(1, 2), 0, 4},
- {1, M(1, 3), 0, 4},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {1, M(3, 1), 2, 1},
- {1, M(3, 1), 1, 1},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {1, M(2, 0), 2, 1},
- };
-
- #elif defined(__IMXRT1052__)
-
- const struct pwm_pin_info_struct pwm_pin_info[] = {
- {1, M(1, 1), 0, 4},
- {1, M(1, 0), 0, 4},
- {1, M(4, 2), 1, 1},
- {1, M(4, 2), 2, 1},
- {1, M(2, 0), 1, 1},
- {1, M(2, 0), 2, 1},
- {1, M(1, 3), 2, 6},
- {1, M(1, 3), 1, 6},
- {1, M(2, 2), 1, 2},
- {1, M(2, 2), 2, 2},
- {2, M(1, 0), 0, 1},
- {2, M(1, 2), 0, 1},
- {2, M(1, 1), 0, 1},
- {2, M(2, 0), 0, 1},
- {2, M(3, 2), 0, 1},
- {2, M(3, 3), 0, 1},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {2, M(3, 1), 0, 1},
- {2, M(3, 0), 0, 1},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {1, M(4, 0), 1, 1},
- {1, M(4, 1), 1, 1},
- {1, M(1, 2), 0, 4},
- {1, M(1, 3), 0, 4},
- {0, M(1, 0), 0, 0},
- {0, M(1, 0), 0, 0},
- {1, M(3, 1), 2, 1},
- {1, M(3, 1), 1, 1},
- {1, M(1, 0), 2, 1},
- {1, M(1, 0), 1, 1},
- {0, M(1, 0), 0, 0},
- {1, M(2, 1), 1, 1},
- };
-
- #endif
-
- void flexpwmWrite(IMXRT_FLEXPWM_t *p, unsigned int submodule, uint8_t channel, uint16_t val)
- {
- uint16_t mask = 1 << submodule;
- uint32_t modulo = p->SM[submodule].VAL1;
- uint32_t cval = ((uint32_t)val * (modulo + 1)) >> analog_write_res;
- if (cval > modulo) cval = modulo;
-
-
-
- p->MCTRL |= FLEXPWM_MCTRL_CLDOK(mask);
- switch (channel) {
- case 0:
- p->SM[submodule].VAL0 = modulo - cval;
- p->OUTEN |= FLEXPWM_OUTEN_PWMX_EN(mask);
-
- break;
- case 1:
- p->SM[submodule].VAL3 = cval;
- p->OUTEN |= FLEXPWM_OUTEN_PWMA_EN(mask);
-
- break;
- case 2:
- p->SM[submodule].VAL5 = cval;
- p->OUTEN |= FLEXPWM_OUTEN_PWMB_EN(mask);
-
- }
- p->MCTRL |= FLEXPWM_MCTRL_LDOK(mask);
- }
-
- void flexpwmFrequency(IMXRT_FLEXPWM_t *p, unsigned int submodule, uint8_t channel, float frequency)
- {
- uint16_t mask = 1 << submodule;
- uint32_t olddiv = p->SM[submodule].VAL1;
- uint32_t newdiv = (uint32_t)((float)F_BUS_ACTUAL / frequency + 0.5);
- uint32_t prescale = 0;
-
- while (newdiv > 65535 && prescale < 7) {
- newdiv = newdiv >> 1;
- prescale = prescale + 1;
- }
- if (newdiv > 65535) {
- newdiv = 65535;
- } else if (newdiv < 2) {
- newdiv = 2;
- }
-
- 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].VAL0 = (p->SM[submodule].VAL0 * newdiv) / olddiv;
- p->SM[submodule].VAL3 = (p->SM[submodule].VAL3 * newdiv) / olddiv;
- p->SM[submodule].VAL5 = (p->SM[submodule].VAL5 * newdiv) / olddiv;
- p->MCTRL |= FLEXPWM_MCTRL_LDOK(mask);
- }
-
- void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val)
- {
- uint32_t modulo = 65537 - p->CH[submodule].LOAD + p->CH[submodule].CMPLD1;
- uint32_t high = ((uint32_t)val * (modulo - 1)) >> analog_write_res;
- if (high >= modulo) high = modulo - 1;
-
-
-
- uint32_t low = modulo - high;
-
-
- p->CH[submodule].LOAD = 65537 - low;
- p->CH[submodule].CMPLD1 = high;
- }
-
- void quadtimerFrequency(IMXRT_TMR_t *p, unsigned int submodule, float frequency)
- {
- uint32_t newdiv = (uint32_t)((float)F_BUS_ACTUAL / frequency + 0.5);
- uint32_t prescale = 0;
-
- while (newdiv > 65534 && prescale < 7) {
- newdiv = newdiv >> 1;
- prescale = prescale + 1;
- }
- if (newdiv > 65534) {
- newdiv = 65534;
- } else if (newdiv < 2) {
- newdiv = 2;
- }
-
- uint32_t oldhigh = p->CH[submodule].CMPLD1;
- uint32_t oldlow = 65537 - p->CH[submodule].LOAD;
- uint32_t high = (oldhigh * newdiv) / (oldhigh + oldlow);
-
- uint32_t low = newdiv - high;
-
- p->CH[submodule].LOAD = 65537 - low;
- p->CH[submodule].CMPLD1 = high;
- p->CH[submodule].CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + prescale) |
- TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(6);
- }
-
- void analogWrite(uint8_t pin, int val)
- {
- const struct pwm_pin_info_struct *info;
-
- if (pin >= CORE_NUM_DIGITAL) return;
-
- info = pwm_pin_info + pin;
- if (info->type == 1) {
-
- 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;
- }
- flexpwmWrite(flexpwm, info->module & 0x03, info->channel, val);
- } else if (info->type == 2) {
-
- IMXRT_TMR_t *qtimer;
- switch ((info->module >> 4) & 3) {
- case 0: qtimer = &IMXRT_TMR1; break;
- case 1: qtimer = &IMXRT_TMR2; break;
- case 2: qtimer = &IMXRT_TMR3; break;
- default: qtimer = &IMXRT_TMR4;
- }
- quadtimerWrite(qtimer, info->module & 0x03, val);
- } else {
- return;
- }
- *(portConfigRegister(pin)) = info->muxval;
-
- }
-
- void analogWriteFrequency(uint8_t pin, float frequency)
- {
- const struct pwm_pin_info_struct *info;
-
- if (pin >= CORE_NUM_DIGITAL) return;
-
- info = pwm_pin_info + pin;
- if (info->type == 1) {
-
- 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;
- }
- flexpwmFrequency(flexpwm, info->module & 0x03, info->channel, frequency);
- } else if (info->type == 2) {
-
- IMXRT_TMR_t *qtimer;
- switch ((info->module >> 4) & 3) {
- case 0: qtimer = &IMXRT_TMR1; break;
- case 1: qtimer = &IMXRT_TMR2; break;
- case 2: qtimer = &IMXRT_TMR3; break;
- default: qtimer = &IMXRT_TMR4;
- }
- quadtimerFrequency(qtimer, info->module & 0x03, frequency);
- }
- }
-
- void flexpwm_init(IMXRT_FLEXPWM_t *p)
- {
- int i;
-
- p->FCTRL0 = FLEXPWM_FCTRL0_FLVL(15);
- p->FSTS0 = 0x000F;
- p->FFILT0 = 0;
- p->MCTRL |= FLEXPWM_MCTRL_CLDOK(15);
- for (i=0; i < 4; i++) {
- p->SM[i].CTRL2 = FLEXPWM_SMCTRL2_INDEP | FLEXPWM_SMCTRL2_WAITEN
- | FLEXPWM_SMCTRL2_DBGEN;
- p->SM[i].CTRL = FLEXPWM_SMCTRL_FULL;
- p->SM[i].OCTRL = 0;
- p->SM[i].DTCNT0 = 0;
- p->SM[i].INIT = 0;
- p->SM[i].VAL0 = 0;
- p->SM[i].VAL1 = 33464;
- p->SM[i].VAL2 = 0;
- p->SM[i].VAL3 = 0;
- p->SM[i].VAL4 = 0;
- p->SM[i].VAL5 = 0;
- }
- p->MCTRL |= FLEXPWM_MCTRL_LDOK(15);
- p->MCTRL |= FLEXPWM_MCTRL_RUN(15);
- }
-
- void quadtimer_init(IMXRT_TMR_t *p)
- {
- int i;
-
- for (i=0; i < 4; i++) {
- p->CH[i].CTRL = 0;
- p->CH[i].CNTR = 0;
- p->CH[i].SCTRL = TMR_SCTRL_OEN | TMR_SCTRL_OPS | TMR_SCTRL_VAL | TMR_SCTRL_FORCE;
- p->CH[i].CSCTRL = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_ALT_LOAD;
-
- p->CH[i].LOAD = 24000;
- p->CH[i].COMP1 = 0;
- p->CH[i].CMPLD1 = 0;
- p->CH[i].CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) |
- TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(6);
- }
- }
-
- void pwm_init(void)
- {
-
- CCM_CCGR4 |= CCM_CCGR4_PWM1(CCM_CCGR_ON) | CCM_CCGR4_PWM2(CCM_CCGR_ON) |
- CCM_CCGR4_PWM3(CCM_CCGR_ON) | CCM_CCGR4_PWM4(CCM_CCGR_ON);
- CCM_CCGR6 |= CCM_CCGR6_QTIMER1(CCM_CCGR_ON) | CCM_CCGR6_QTIMER2(CCM_CCGR_ON) |
- CCM_CCGR6_QTIMER3(CCM_CCGR_ON) | CCM_CCGR6_QTIMER4(CCM_CCGR_ON);
- flexpwm_init(&IMXRT_FLEXPWM1);
- flexpwm_init(&IMXRT_FLEXPWM2);
- flexpwm_init(&IMXRT_FLEXPWM3);
- flexpwm_init(&IMXRT_FLEXPWM4);
- quadtimer_init(&IMXRT_TMR1);
- quadtimer_init(&IMXRT_TMR2);
- quadtimer_init(&IMXRT_TMR3);
- }
-
-
-
- void xbar_connect(unsigned int input, unsigned int output)
- {
- if (input >= 88) return;
- if (output >= 132) return;
- #if 1
- volatile uint16_t *xbar = &XBARA1_SEL0 + (output / 2);
- uint16_t val = *xbar;
- if (!(output & 1)) {
- val = (val & 0xFF00) | input;
- } else {
- val = (val & 0x00FF) | (input << 8);
- }
- *xbar = val;
- #else
-
- volatile uint8_t *xbar = (volatile uint8_t *)XBARA1_SEL0;
- xbar[output] = input;
- #endif
- }
-
- uint32_t analogWriteRes(uint32_t bits)
- {
- uint32_t prior;
- if (bits < 1) {
- bits = 1;
- } else if (bits > 16) {
- bits = 16;
- }
- prior = analog_write_res;
- analog_write_res = bits;
- return prior;
- }
-
-
|