11#include " teensy4_mcu.h"
22#include " ../../../drivers/hardware_specific/teensy/teensy4_mcu.h"
3+ #include " ../../../common/foc_utils.h"
34
45// if defined
56// - Teensy 4.0
1213//
1314// the flags are defined in the imxrt.h file
1415// https://github.com/PaulStoffregen/cores/blob/dd6aa8419ee173a0a6593eab669fbff54ed85f48/teensy4/imxrt.h#L9662
15- int flextim__submodule_to_trig (IMXRT_FLEXPWM_t* flexpwm, int submodule){
16+ int flexpwm_submodule_to_trig (IMXRT_FLEXPWM_t* flexpwm, int submodule){
1617 if (submodule <0 && submodule > 3 ) return -1 ;
1718 if (flexpwm == &IMXRT_FLEXPWM1){
1819 return XBARA1_IN_FLEXPWM1_PWM1_OUT_TRIG0 + submodule;
@@ -26,32 +27,45 @@ int flextim__submodule_to_trig(IMXRT_FLEXPWM_t* flexpwm, int submodule){
2627 return -1 ;
2728}
2829
29- volatile uint32_t val0, val1;
30+ volatile uint32_t val0, val1, val2 ;
3031
31- void read_currents (uint32_t *a, uint32_t *b){
32+ void read_currents (uint32_t *a, uint32_t *b, uint32_t *c= nullptr ){
3233 *a = val0;
3334 *b = val1;
35+ *c = val2;
3436}
3537
3638// interrupt service routine for the ADC_ETC0
3739// reading the ADC values and clearing the interrupt
3840void adcetc0_isr () {
3941 digitalWrite (30 ,HIGH);
40- ADC_ETC_DONE0_1_IRQ |= 1 ; // clear
42+ // page 3509 , section 66.5.1.3.3
43+ ADC_ETC_DONE0_1_IRQ |= 1 ; // clear Done0 for trg0 at 1st bit
4144 val0 = ADC_ETC_TRIG0_RESULT_1_0 & 4095 ;
4245 val1 = (ADC_ETC_TRIG0_RESULT_1_0 >> 16 ) & 4095 ;
4346 asm (" dsb" );
4447 digitalWrite (30 ,LOW);
4548}
4649
50+
51+ void adcetc1_isr () {
52+ digitalWrite (30 ,HIGH);
53+ // page 3509 , section 66.5.1.3.3
54+ ADC_ETC_DONE0_1_IRQ |= 1 << 16 ; // clear Done1 for trg0 at 16th bit
55+ val2 = ADC_ETC_TRIG0_RESULT_3_2 & 4095 ;
56+ // val2 = (ADC_ETC_TRIG0_RESULT_3_2 >> 16) & 4095;
57+ asm (" dsb" );
58+ digitalWrite (30 ,LOW);
59+ }
60+
4761// function initializing the ADC2
4862// and the ADC_ETC trigger for the low side current sensing
49- void adc1_init () {
63+ void adc1_init (int pin1, int pin2, int pin3=NOT_SET ) {
5064 // Tried many configurations, but this seems to be best:
5165 ADC1_CFG = ADC_CFG_OVWREN // Allow overwriting of the next converted Data onto the existing
5266 | ADC_CFG_ADICLK (0 ) // input clock select - IPG clock
5367 | ADC_CFG_MODE (2 ) // 12-bit conversion 0 8-bit conversion 1 10-bit conversion 2 12-bit conversion
54- | ADC_CFG_ADIV (2 ) // Input clock / 4
68+ | ADC_CFG_ADIV (1 ) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4)
5569 | ADC_CFG_ADSTS (0 ) // Sample period (ADC clocks) = 3 if ADLSMP=0b
5670 | ADC_CFG_ADHSC // High speed operation
5771 | ADC_CFG_ADTRG; // Hardware trigger selected
@@ -63,7 +77,9 @@ void adc1_init() {
6377
6478 ADC1_HC0 = 16 ; // ADC_ETC channel
6579 // use the second interrupt if necessary (for more than 2 channels)
66- // ADC1_HC1 = 16;
80+ if (_isset (pin3)) {
81+ ADC1_HC1 = 16 ;
82+ }
6783}
6884
6985// function initializing the ADC2
@@ -75,7 +91,7 @@ void adc2_init(){
7591 ADC1_CFG = ADC_CFG_OVWREN // Allow overwriting of the next converted Data onto the existing
7692 | ADC_CFG_ADICLK (0 ) // input clock select - IPG clock
7793 | ADC_CFG_MODE (2 ) // 12-bit conversion 0 8-bit conversion 1 10-bit conversion 2 12-bit conversion
78- | ADC_CFG_ADIV (2 ) // Input clock / 4
94+ | ADC_CFG_ADIV (1 ) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4)
7995 | ADC_CFG_ADSTS (0 ) // Sample period (ADC clocks) = 3 if ADLSMP=0b
8096 | ADC_CFG_ADHSC // High speed operation
8197 | ADC_CFG_ADTRG; // Hardware trigger selected
@@ -89,10 +105,13 @@ void adc2_init(){
89105 // ADC2_HC1 = 16;
90106}
91107
92- void adc_etc_init (int pin1, int pin2) {
108+ // function initializing the ADC_ETC trigger for the low side current sensing
109+ // it uses only the ADC1
110+ // if the pin3 is not set it uses only 2 channels
111+ void adc_etc_init (int pin1, int pin2, int pin3=NOT_SET) {
93112 ADC_ETC_CTRL &= ~(1 << 31 ); // SOFTRST
94113 ADC_ETC_CTRL = 0x40000001 ; // start with trigger 0
95- ADC_ETC_TRIG0_CTRL = 0x100 ; // chainlength -1
114+ ADC_ETC_TRIG0_CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN ( _isset (pin3) ? 2 : 1 ) ; // 2 if 3 channels, 1 if 2 channels
96115
97116 // ADC1 7 8, chain channel, HWTS, IE, B2B
98117 // pg 3516, section 66.5.1.8
@@ -109,11 +128,18 @@ void adc_etc_init(int pin1, int pin2) {
109128 attachInterruptVector (IRQ_ADC_ETC0, adcetc0_isr);
110129 NVIC_ENABLE_IRQ (IRQ_ADC_ETC0);
111130 // use the second interrupt if necessary (for more than 2 channels)
112- // attachInterruptVector(IRQ_ADC_ETC1, adcetc1_isr);
113- // NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
131+ if (_isset (pin3)) {
132+ ADC_ETC_TRIG0_CHAIN_3_2 =
133+ ADC_ETC_TRIG_CHAIN_IE0 (2 ) | // interrupt when Done1
134+ ADC_ETC_TRIG_CHAIN_B2B0 | // Enable B2B, back to back ADC trigger
135+ ADC_ETC_TRIG_CHAIN_HWTS0 (1 ) |
136+ ADC_ETC_TRIG_CHAIN_CSEL0 (pin_to_channel[pin3]);
137+
138+ attachInterruptVector (IRQ_ADC_ETC1, adcetc1_isr);
139+ NVIC_ENABLE_IRQ (IRQ_ADC_ETC1);
140+ }
114141}
115142
116-
117143void xbar_connect (unsigned int input, unsigned int output)
118144{
119145 if (input >= 88 ) return ;
@@ -135,12 +161,15 @@ void xbar_init() {
135161// function reading an ADC value and returning the read voltage
136162float _readADCVoltageLowSide (const int pinA, const void * cs_params){
137163
164+ if (!_isset (pinA)) return 0.0 ; // if the pin is not set return 0
138165 GenericCurrentSenseParams* params = (GenericCurrentSenseParams*) cs_params;
139166 float adc_voltage_conv = params->adc_voltage_conv ;
140167 if (pinA == params->pins [0 ]) {
141168 return val0 * adc_voltage_conv;
142169 } else if (pinA == params->pins [1 ]) {
143170 return val1 * adc_voltage_conv;
171+ }else if (pinA == params->pins [2 ]) {
172+ return val2 * adc_voltage_conv;
144173 }
145174 return 0.0 ;
146175}
@@ -149,18 +178,33 @@ float _readADCVoltageLowSide(const int pinA, const void* cs_params){
149178// cannot do much but
150179void * _configureADCLowSide (const void * driver_params, const int pinA,const int pinB,const int pinC){
151180 _UNUSED (driver_params);
181+ // _UNUSED(pinC);
152182
153183 pinMode (30 ,OUTPUT);
154184
155185 if ( _isset (pinA) ) pinMode (pinA, INPUT);
156186 if ( _isset (pinB) ) pinMode (pinB, INPUT);
157187 if ( _isset (pinC) ) pinMode (pinC, INPUT);
158188
159- adc1_init ();
160- adc_etc_init (pinA, pinB);
189+ // check if either of the pins are not set
190+ // and dont use it if it isn't
191+ int pin_count = 0 ;
192+ int pins[3 ] = {NOT_SET, NOT_SET, NOT_SET};
193+ if (_isset (pinA)) pins[pin_count++] = pinA;
194+ if (_isset (pinB)) pins[pin_count++] = pinB;
195+ if (_isset (pinC)) pins[pin_count++] = pinC;
196+
197+
198+ adc1_init (pins[0 ], pins[1 ], pins[2 ]);
199+ SIMPLEFOC_DEBUG (" pins: " ,pins[0 ]);
200+ SIMPLEFOC_DEBUG (" pins: " ,pins[1 ]);
201+ SIMPLEFOC_DEBUG (" pins: " ,pins[2 ]);
202+ adc_etc_init (pins[0 ], pins[1 ], pins[2 ]);
203+
161204 xbar_init ();
205+
162206 GenericCurrentSenseParams* params = new GenericCurrentSenseParams {
163- .pins = { pinA, pinB, pinC },
207+ .pins = {pins[ 0 ], pins[ 1 ], pins[ 2 ] },
164208 .adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION)
165209 };
166210 return params;
@@ -172,17 +216,18 @@ void _driverSyncLowSide(void* driver_params, void* cs_params){
172216 IMXRT_FLEXPWM_t* flexpwm = par->flextimers [0 ];
173217 int submodule = par->submodules [0 ];
174218
175- // do xbar connect here
176-
177- int xbar_trig_pwm = flextim__submodule_to_trig (flexpwm, submodule);
219+ // find the xbar trigger for the flexpwm
220+ int xbar_trig_pwm = flexpwm_submodule_to_trig (flexpwm, submodule);
178221 if (xbar_trig_pwm<0 ) return ;
179222
223+ // allow theFlexPWM to trigger the ADC_ETC
180224 xbar_connect ((uint32_t )xbar_trig_pwm, XBARA1_OUT_ADC_ETC_TRIG00); // FlexPWM to adc_etc
181225
182- // setup the ADC_ETC trigger
226+ // setup the ADC_ETC trigger to be triggered by the FlexPWM channel 4 (val4)
183227 flexpwm->SM [submodule].TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN (1 <<4 );
184- // setup this val4 for interrupt on val5 match for ADC sync
185- // reading two ARC takes about 5us. So put the interrupt 2.5us befor the center
228+ // setup this val4 for interrupt on match for ADC sync
229+ // this code assumes that the val4 is not used for anything else!
230+ // reading two ADC takes about 2.5us. So put the interrupt 2.5us befor the center
186231 flexpwm->SM [submodule].VAL4 = -int (2.5e-6 *par->pwm_frequency *flexpwm->SM [submodule].VAL1 ) ; // 2.5us before center
187232
188233}
0 commit comments