Forum Rule: Always post complete source code & details to reproduce any issue!
Page 4 of 5 FirstFirst ... 2 3 4 5 LastLast
Results 76 to 100 of 101

Thread: Teensyduino 1.48 Beta #3

  1. #76
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE
    Did some experimenting using loopback and pin 14 for the Rx pin. In our lib I added IOMUXC_QTIMER3_TIMER2_SELECT_INPUT = 0x01; //pin 14 to the begin function and it hung the T4 - then it would loose connection to the usb.

    So as a test I modified @manitou's original standalone pulsepositioninput sketch to use pin 14 for tx and used the lib functions for transmitting on pin 9 and it worked like a charm - output: 600.03 input: 600.08. Heres the sketch modified to use pin 14 for rx:
    Code:
    // PPM in, report pulse widths
    //  test with PulsePosition output pin 9 to T4 pin 11
    // QTIMER1   pin capture test  qtmr 1 ch 2  pin 11 B0_02,  ch 52
    // free-running 16-bit timer
    // QTIMER oflow interrupt no workee,  use 0xffff compare for 32-bit
    // polarity TMR_SCTRL_IPS
    #define PRREG(x) Serial.printf(#x" 0x%x\n",x);
    #include <PulsePosition_t4.h>
    PulsePositionOutput myOut;
    
    #define PULSEPOSITION_MAXCHANNELS 16
    uint32_t pulse_width[PULSEPOSITION_MAXCHANNELS+1];
    uint32_t pulse_buffer[PULSEPOSITION_MAXCHANNELS+1];
    uint32_t write_index, prev, total_channels;
    
    #define CLOCKS_PER_MICROSECOND (150./4)  // pcs 8+2
    #define RX_MINIMUM_SPACE   3500.0
    #define RX_MINIMUM_SPACE_CLOCKS   (uint32_t)(RX_MINIMUM_SPACE * CLOCKS_PER_MICROSECOND)
    
    
    volatile uint32_t ticks, overflow_count;
    volatile bool overflow_inc, available_flag;
    
    void my_isr() {  // capture and compare
      if (TMR3_CSCTRL2 & TMR_CSCTRL_TCF1) { // compare rollover
        TMR3_CSCTRL2 &= ~(TMR_CSCTRL_TCF1);  // clear
        overflow_count++;
        overflow_inc = true;
      }
      if (TMR3_SCTRL2 & TMR_SCTRL_IEF) { // capture
        uint32_t val, count;
        TMR3_SCTRL2 &= ~(TMR_SCTRL_IEF);  // clear
        val = TMR3_CAPT2;
        count = overflow_count;
        if (val > 0xE000 && overflow_inc) count--;
        val |= (count << 16);
        count = val - prev;
        prev = val;
        if (count >= RX_MINIMUM_SPACE_CLOCKS) {
          if (write_index < 255) {
            for (int i = 0; i < write_index; i++) {
              pulse_buffer[i] = pulse_width[i];
            }
            total_channels = write_index;
            available_flag = true;
          }
          write_index = 0;
        } else {
          if (write_index < PULSEPOSITION_MAXCHANNELS) {
            pulse_width[write_index++] = count;
          }
        }
      }
      ticks++;
      asm volatile ("dsb");  // wait for clear  memory barrier
      overflow_inc = false;
    }
    
    void capture_init() {
      CCM_CCGR6 |= CCM_CCGR6_QTIMER3(CCM_CCGR_ON);
    
      TMR3_CTRL2 = 0; // stop
      TMR3_LOAD2 = 0;
      TMR3_CSCTRL2 = 0;
      TMR3_LOAD2 = 0;  // start val after compare
      TMR3_COMP12 = 0xffff;  // count up to this val, interrupt,  and start again
      TMR3_CMPLD12 = 0xffff;
    
      TMR3_SCTRL2 = TMR_SCTRL_CAPTURE_MODE(1);  //rising
      attachInterruptVector(IRQ_QTIMER3, my_isr);
      TMR3_SCTRL2 |= TMR_SCTRL_IEFIE;  // enable compare interrupt
      TMR3_CSCTRL2 = TMR_CSCTRL_TCF1EN;  // enable capture interrupt
      NVIC_SET_PRIORITY(IRQ_QTIMER3, 32);
      NVIC_ENABLE_IRQ(IRQ_QTIMER3);
      TMR3_CTRL2 =  TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(0) | TMR_CTRL_LENGTH ; // prescale
      *(portConfigRegister(14)) = 1;  // ALT 1
      IOMUXC_QTIMER3_TIMER2_SELECT_INPUT = 0x01;  //pin 14
    }
    
    int ppmIn_available() {
      uint32_t total;
      bool flag;
    
      __disable_irq();
      flag = available_flag;
      total = total_channels;
      __enable_irq();
      if (flag) return total;
      return -1;
    }
    
    float ppmIn_read(uint8_t channel) {
      uint32_t total, index, value = 0;
    
      if (channel == 0) return 0.0;
      index = channel - 1;
      __disable_irq();
      total = total_channels;
      if (index < total) value = pulse_buffer[index];
      if (channel >= total) available_flag = false;
      __enable_irq();
      return (float)value / (float)CLOCKS_PER_MICROSECOND;
    }
    
    void setup()   {
      Serial.begin(9600);
      while (!Serial);
      delay(1000);
      myOut.begin(9);  // connect pins 9 and 10 together...
      myOut.write(1, 600.03);
      write_index = 255;
      available_flag = false;
      capture_init();
    
      PRREG(TMR3_SCTRL2);
      PRREG(TMR3_CSCTRL2);
      PRREG(TMR3_CTRL2);
      PRREG(TMR3_LOAD2);
      PRREG(TMR3_COMP12);
      PRREG(TMR3_CMPLD12);
      PRREG(TMR3_COMP22);
      PRREG(TMR3_CMPLD22);
    }
    
    void loop() {
      int i, num;
      static int count = 0;
    
      // Every time new data arrives, simply print it
      // to the Arduino Serial Monitor.
      num = ppmIn_available();
      if (num > 0) {
        count = count + 1;
        Serial.print(count);
        Serial.print(" :  ");
        for (i = 1; i <= num; i++) {
          float val = ppmIn_read(i);
          Serial.print(val);
          Serial.print("  ");
        }
        Serial.println();
      }
    }
    Last edited by mjs513; 10-29-2019 at 11:38 AM.

  2. #77
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,236
    Re: daisy register
    I was lucky in my QTIMER proof-of-concepts, i just tried pins 11 and 6 and didn't stumble on a daisy register. However, in the last few days I've been playing with eflexPWM timers to do PPM input and output, and pin 8 did require a SELECT_INPUT daisy register config. (Paul's T4 FrequencyMeasure uses eflexPWM capture on pin 22 and also requires a daisy register.)

    @mjs513, the programming gods are smiling on you: TMR_CTRL_SCS(14) should be TMR_CTRL_SCS(2) for pin 14 (QT3_2). Conveniently 14 mod 4 = 2

    FWIW, i haven't been able to get PPM out to work with long (> 16bit) pulse width using flexPWM timer. I did get PPM in to work with flexPWM timer (capture and overflow interrupts).
    https://github.com/manitou48/teensy4...ter/ppminf.ino
    Last edited by manitou; 10-29-2019 at 12:07 PM.

  3. #78
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @manitou - @KurtE

    That's what I get for playing with this when I can't sleep at 2 in the morning Knew it was channel but still put pin, argh.

    Anyway, what to try the input example with different pins outside the lib structure to see if changes would work. Daisy Chain worked for pin 14 but not in the lib. That's one test. The second test I just did was to use pin 13 for input (QT2_0). And unless I forgot to change something doesn't look like pin 13 will work as an input pin unless something else has to change: EDIT: YEP FORGOT the Daisy Chain - once I do that it works as well.
    Code:
    // PPM in, report pulse widths
    //  test with PulsePosition output pin 9 to T4 pin 11
    // QTIMER1   pin capture test  qtmr 1 ch 2  pin 11 B0_02,  ch 52
    // free-running 16-bit timer
    // QTIMER oflow interrupt no workee,  use 0xffff compare for 32-bit
    // polarity TMR_SCTRL_IPS
    #define PRREG(x) Serial.printf(#x" 0x%x\n",x);
    #include <PulsePosition_t4.h>
    PulsePositionOutput myOut;
    
    #define PULSEPOSITION_MAXCHANNELS 16
    uint32_t pulse_width[PULSEPOSITION_MAXCHANNELS+1];
    uint32_t pulse_buffer[PULSEPOSITION_MAXCHANNELS+1];
    uint32_t write_index, prev, total_channels;
    
    #define CLOCKS_PER_MICROSECOND (150./4)  // pcs 8+2
    #define RX_MINIMUM_SPACE   3500.0
    #define RX_MINIMUM_SPACE_CLOCKS   (uint32_t)(RX_MINIMUM_SPACE * CLOCKS_PER_MICROSECOND)
    
    
    volatile uint32_t ticks, overflow_count;
    volatile bool overflow_inc, available_flag;
    
    void my_isr() {  // capture and compare
      if (TMR2_CSCTRL0 & TMR_CSCTRL_TCF1) { // compare rollover
        TMR2_CSCTRL0 &= ~(TMR_CSCTRL_TCF1);  // clear
        overflow_count++;
        overflow_inc = true;
      }
      if (TMR2_SCTRL0 & TMR_SCTRL_IEF) { // capture
        uint32_t val, count;
        TMR2_SCTRL0 &= ~(TMR_SCTRL_IEF);  // clear
        val = TMR2_CAPT0;
        count = overflow_count;
        if (val > 0xE000 && overflow_inc) count--;
        val |= (count << 16);
        count = val - prev;
        prev = val;
        if (count >= RX_MINIMUM_SPACE_CLOCKS) {
          if (write_index < 255) {
            for (int i = 0; i < write_index; i++) {
              pulse_buffer[i] = pulse_width[i];
            }
            total_channels = write_index;
            available_flag = true;
          }
          write_index = 0;
        } else {
          if (write_index < PULSEPOSITION_MAXCHANNELS) {
            pulse_width[write_index++] = count;
          }
        }
      }
      ticks++;
      asm volatile ("dsb");  // wait for clear  memory barrier
      overflow_inc = false;
    }
    
    void capture_init() {
      CCM_CCGR6 |= CCM_CCGR6_QTIMER2(CCM_CCGR_ON);
    
      TMR2_CTRL0 = 0; // stop
      TMR3_LOAD0 = 0;
      TMR2_CSCTRL0 = 0;
      TMR2_LOAD0 = 0;  // start val after compare
      TMR2_COMP10 = 0xffff;  // count up to this val, interrupt,  and start again
      TMR2_CMPLD10 = 0xffff;
    
      TMR2_SCTRL0 = TMR_SCTRL_CAPTURE_MODE(1);  //rising
      attachInterruptVector(IRQ_QTIMER2, my_isr);
      TMR2_SCTRL0 |= TMR_SCTRL_IEFIE;  // enable compare interrupt
      TMR2_CSCTRL0 = TMR_CSCTRL_TCF1EN;  // enable capture interrupt
      NVIC_SET_PRIORITY(IRQ_QTIMER2, 32);
      NVIC_ENABLE_IRQ(IRQ_QTIMER2);
      TMR2_CTRL0 =  TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(0) | TMR_CTRL_LENGTH ; // prescale
      *(portConfigRegister(13)) = 1;  // ALT 1
    IOMUXC_QTIMER2_TIMER0_SELECT_INPUT = 0x01;  //pin 13
    //IOMUXC_QTIMER3_TIMER2_SELECT_INPUT = 0x01;  //pin 14
    }
    
    int ppmIn_available() {
      uint32_t total;
      bool flag;
    
      __disable_irq();
      flag = available_flag;
      total = total_channels;
      __enable_irq();
      if (flag) return total;
      return -1;
    }
    
    float ppmIn_read(uint8_t channel) {
      uint32_t total, index, value = 0;
    
      if (channel == 0) return 0.0;
      index = channel - 1;
      __disable_irq();
      total = total_channels;
      if (index < total) value = pulse_buffer[index];
      if (channel >= total) available_flag = false;
      __enable_irq();
      return (float)value / (float)CLOCKS_PER_MICROSECOND;
    }
    
    void setup()   {
      Serial.begin(9600);
      while (!Serial);
      delay(1000);
      myOut.begin(9);  // connect pins 9 and 10 together...
      myOut.write(1, 600.03);
      write_index = 255;
      available_flag = false;
      capture_init();
    
      PRREG(TMR2_SCTRL0);
      PRREG(TMR2_CSCTRL0);
      PRREG(TMR2_CTRL0);
      PRREG(TMR2_LOAD0);
      PRREG(TMR2_COMP10);
      PRREG(TMR2_CMPLD10);
      PRREG(TMR2_COMP20);
      PRREG(TMR2_CMPLD20);
    }
    
    void loop() {
      int i, num;
      static int count = 0;
    
      // Every time new data arrives, simply print it
      // to the Arduino Serial Monitor.
      num = ppmIn_available();
      if (num > 0) {
        count = count + 1;
        Serial.print(count);
        Serial.print(" :  ");
        for (i = 1; i <= num; i++) {
          float val = ppmIn_read(i);
          Serial.print(val);
          Serial.print("  ");
        }
        Serial.println();
      }
    }
    EDIT: Interestingly Pin18 works without setting the daisy chain register - probably because its already 0? Pin 19 works but you need to set the IOMUX register.

    EDIT1: pin 6 does work as input, but pins 11, 12 do work as input getting the correct values
    Last edited by mjs513; 10-29-2019 at 12:15 PM.

  4. #79
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    RE: FOUND THE HANG FOR PINS OTHER THAN 11

    Hangs on this line:
    Code:
    	//set Mux for Tx Pin - all timers on ALT1
    	*(portConfigRegister(rxPin)) = 1;
    Yes I changed pin variable name. Works if you set it to 0 but that was just curiosity.

  5. #80
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,236
    Quote Originally Posted by mjs513 View Post
    RE: FOUND THE HANG FOR PINS OTHER THAN 11

    Hangs on this line:
    Code:
    	//set Mux for Tx Pin - all timers on ALT1
    	*(portConfigRegister(rxPin)) = 1;
    Yes I changed pin variable name. Works if you set it to 0 but that was just curiosity.
    maybe try *(portConfigRegister(rxPin)) = 1 | 0x10;

  6. #81
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    Good morning...

    Yep - I have seen it hang at or near there... Sometimes it goes a bit longer... before hang...
    Code:
    bool PulsePositionInput::begin(uint8_t pin)
    {
    	for (idx_channel = 0; idx_channel < _hardware_count; idx_channel++) {
    		if (hardware[idx_channel].pin == pin) break; 
    	}
    	if (idx_channel == _hardware_count) return false;
    
    	// make sure the appropriate clock gate is enabled.
    	*hardware[idx_channel].clock_gate_register |= hardware[idx_channel].clock_gate_mask;
    
    	uint8_t channel =  hardware[idx_channel].channel;
    	volatile IMXRT_TMR_CH_t *tmr_ch = &hardware[idx_channel].tmr->CH[channel];
    
    	tmr_ch->CTRL = 0; // stop
    	tmr_ch->CNTR = 0;
    	tmr_ch->LOAD = 0;
    	tmr_ch->CSCTRL = 0;
    	tmr_ch->LOAD = 0;  // start val after compare
    	tmr_ch->COMP1 = 0xffff;  // count up to this val, interrupt,  and start again
    	tmr_ch->CMPLD1 = 0xffff;
    
    	if(outPolarity == 0){
    	  tmr_ch->SCTRL = TMR_SCTRL_CAPTURE_MODE(2);  //falling
    	} else {
    	  tmr_ch->SCTRL = TMR_SCTRL_CAPTURE_MODE(1);  //rising
    	}
    	attachInterruptVector(hardware[idx_channel].interrupt, hardware[idx_channel].isr);
    	tmr_ch->SCTRL |= TMR_SCTRL_IEFIE | TMR_SCTRL_TOFIE;  // enable compare interrupt as well as overflow
    	// tmr_ch->CSCTRL = TMR_CSCTRL_TCF1EN;  // enable capture interrupt
    	NVIC_SET_PRIORITY(hardware[idx_channel].interrupt, 32);
    	NVIC_ENABLE_IRQ(hardware[idx_channel].interrupt);
    	
    //	tmr_ch->CTRL =  TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(channel) | TMR_CTRL_LENGTH ; // prescale
    	tmr_ch->CTRL =  TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(channel) ; // prescale
    	
    	list[idx_channel] = this;
    	
    	//set Mux for Tx Pin - all timers on ALT1
    	*(portConfigRegister(pin)) = 1;
    
    	Serial.printf("PulsePositionInput::begin pin:%d idx: %d CH:%d SC:%x CSC:%x\n", pin, idx_channel, channel, tmr_ch->SCTRL, tmr_ch->CSCTRL); Serial.flush();
    	Serial.printf("  CP1:%x CP2:%x CAPT:%x LOAD:%x \n", (uint16_t)tmr_ch->COMP1, (uint16_t)tmr_ch->COMP2,
    		(uint16_t)tmr_ch->CAPT, (uint16_t)tmr_ch->LOAD); 
    	Serial.flush();
    	Serial.printf("  HOLD:%x CNTR:%x CTRL:%x  SCTRL:%x\n", (uint16_t)tmr_ch->HOLD, (uint16_t)tmr_ch->CNTR, (uint16_t)tmr_ch->CTRL, (uint32_t)tmr_ch->SCTRL); 
    	Serial.flush();
    
    	Serial.printf(" CMPLD1:%x, CMPLD2:%x, FILT:%x DMA:%x ENBL:%x\n",tmr_ch->CMPLD1,
    		tmr_ch->CMPLD2, tmr_ch->FILT, tmr_ch->DMA, tmr_ch->ENBL);
    	Serial.flush();
    
    	Serial.printf("Select Input Regster: %x %d\n", (uint32_t)hardware[idx_channel].select_input_register, hardware[idx_channel].select_val); Serial.flush();
    	if (hardware[idx_channel].select_input_register) {
    		*hardware[idx_channel].select_input_register = hardware[idx_channel].select_val;
    		Serial.println("Select Input completed");Serial.flush();
    	}
    
    
    	
    	return true;
    }
    That is why I put flush output statements around each of the prints to try to force them out. . Almost always I get the first print...

    I have a sort of theory on my test case, that is there is a timing issue... In particular my guess is that maybe I get a pulse on the output before I finish setting up... Again just a guess. My current code sets/clears Pin2 on combined ISR. Does pin 3 on Output ISR and Pin 4 on Input ISR... Will take a look at your stuff again to see if I am missing anything obvious. I will go back to using the match on Input instead of trying to get the overflow to work. I thought one issue might be in overflow that we were setting the TMR_CTRL_LENGTH flag, so I removed it and it did not help.

    Also in your last test case, I saw you were using: TMR2_CTRL0 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(0) | TMR_CTRL_LENGTH ; // prescale
    Did the SCS(0) depend on which channel you were testing?

    Now to next cup of coffee!

  7. #82
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    FYI - I changed around my test app, to init the In before the Out and sure enough everything prints:
    Code:
      myIn.begin(19);
      myOut.begin(9);
      myOut.write(1, 750);
      myOut.write(2, 1500);
      myOut.write(3, 2250);
    Code:
    PulsePositionInput::begin pin:19 idx: 9 CH:0 SC:1440 CSC:300
    Select Input Regster: 401f857c 1
    Select Input completed
      CP1:ffff CP2:0 CAPT:0 LOAD:0 
      HOLD:0 CNTR:23e CTRL:3420  SCTRL:1440
     CMPLD1:ffff, CMPLD2:0, FILT:0 DMA:0 ENBL:0
    But it hangs as expected on the first Input ISR attempt...
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	3 
Size:	44.3 KB 
ID:	18045
    First interrupt is the Output one, which you can see gets processed on the Output ISR handler. But then next ISR request comes in and is NOT processed and we hang... Now to debug

  8. #83
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    Quote Originally Posted by manitou View Post
    maybe try *(portConfigRegister(rxPin)) = 1 | 0x10;
    @manitou - tried both ways with no luck - I also tried to set it directly with (IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01) but that didn't work either. Something strange going on or preventing it from setting.

    @KurtE. For my loopback I am just using the example loopback without the addition of pins 2/3. So in my case it always seems to be dying on setting the pin mux for Rx. I did try a test where I just used output on 1 T4 and input on a second T4 and still the same thing except the T4 used for Rx lost USB and hung. Only pin 6 didn't work as an input pin but I was also transmitting on pin 9 which is the same timer.

    Now more coffee and try and get some sleep

    As for changing SCS(channel) to the appropriate channel. Yep I changed it as I went.

  9. #84
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    The coffee has not kicked in yet, but...

    I took the hang from before and added more print out stuff.

    So like the code I posted above, it now outputs:
    Code:
    PulsePositionInput::begin pin:19 idx: 9 CH:0 SC:1440 CSC:300
    Select Input Regster: 401f857c 1
    Select Input completed
      CP1:ffff CP2:0 CAPT:0 LOAD:0 
      HOLD:0 CNTR:20a CTRL:3420  SCTRL:1440
     CMPLD1:ffff, CMPLD2:0, FILT:0 DMA:0 ENBL:0
    I then mucked with my ISR3 function as using pin 19, which is 3-0...
    Code:
    void PulsePositionBase::isrTimer3()
    {
    	digitalWriteFast(2, HIGH);
    	static uint8_t report_count = 0;
    	if (report_count < 10) {
    		report_count++;
    		Serial1.printf("isrTimer3: %x %x %x %x\n    ", (uint32_t)list[6], (uint32_t)list[7], (uint32_t)list[8], (uint32_t)list[9]);
    		for (uint8_t ch=0; ch < 4; ch++) {
    			Serial1.printf(" %d: %04x %04x", ch, (uint16_t)IMXRT_TMR3.CH[ch].SCTRL,  (uint16_t)IMXRT_TMR3.CH[ch].CSCTRL);
    
    		}
    		Serial1.println();
    	}
    	if (list[6] && TimerCHInPending(&IMXRT_TMR3.CH[2])) { list[6]->isr();}
    	if (list[7] && TimerCHInPending(&IMXRT_TMR3.CH[3])) { list[7]->isr();}
    	if (list[8] && TimerCHInPending(&IMXRT_TMR3.CH[1])) { list[8]->isr();}
    	if (list[9] && TimerCHInPending(&IMXRT_TMR3.CH[0])) { list[9]->isr();}
    	asm volatile ("dsb");  // wait for clear  memory barrier
    	digitalWriteFast(2, LOW);
    }
    Hooked up USB to serial adapter to pin 1, and did a Serial1.begin in setup...
    Now seeing:
    Code:
    isrTimer3: 0 0 0 200013d0
         0: 1d40 0300 1: a10b 1311 2: a10b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 200013d0
         0: 9c40 0310 1: a00b 1311 2: a00b 1311 3: a00b 1311
    isrTimer3: 0 0 0 2000
    And now debugging: So it shows I have list[9] with object as expected. Now
    To look at the SCTRL and CSCTRL values to see which channel is actually triggering the ISR...
    For CH:0 we have
    SCTRL: 9c40 TCF, TOFIE, IEF IEFIE, CAPTURE_MODE(1)
    CSCTRL: 0310 UP, TCF1

    So I think it should trigger the input ISR?

    Oops found it.

    Look at the function:
    Code:
    inline bool TimerCHInPending(volatile IMXRT_TMR_CH_t *tmr_ch) {
     	if ((tmr_ch->CSCTRL & (TMR_CSCTRL_TCF1 | TMR_CSCTRL_TCF1EN)) == (TMR_CSCTRL_TCF1 | TMR_CSCTRL_TCF1EN)) 
     		return true;
     	if ((tmr_ch->SCTRL & (TMR_SCTRL_TOF | TMR_SCTRL_TOFIE)) == (TMR_SCTRL_TOF | TMR_SCTRL_TOFIE)) 
     		return true;
    	if ((IMXRT_TMR1.CH[2].SCTRL & (TMR_SCTRL_IEF | TMR_SCTRL_IEFIE)) == (TMR_SCTRL_IEF | TMR_SCTRL_IEFIE))
    		return true;
    	return false;
    }
    Should be:
    Code:
    inline bool TimerCHInPending(volatile IMXRT_TMR_CH_t *tmr_ch) {
     	if ((tmr_ch->CSCTRL & (TMR_CSCTRL_TCF1 | TMR_CSCTRL_TCF1EN)) == (TMR_CSCTRL_TCF1 | TMR_CSCTRL_TCF1EN)) 
     		return true;
     	if ((tmr_ch->SCTRL & (TMR_SCTRL_TOF | TMR_SCTRL_TOFIE)) == (TMR_SCTRL_TOF | TMR_SCTRL_TOFIE)) 
     		return true;
    	if ((tmr_ch->SCTRL & (TMR_SCTRL_IEF | TMR_SCTRL_IEFIE)) == (TMR_SCTRL_IEF | TMR_SCTRL_IEFIE))
    		return true;
    	return false;
    }

  10. #85
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE


    If you are going to test pin 19 make sure you add: IOMUXC_QTIMER3_TIMER0_SELECT_INPUT = 0x02; //pin 19 to the begin.

    I just tried - no more hangs but no data showing up either. It is getting to the ISR but don't have as many debug statements in yet.

  11. #86
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    @mjs513, Here is my latest stuff, which is working I think on pin 19. You may have the wrong mux value.

    The Mux register/value was added to my hardware table.

    I also made the digitalWriteFast stuff, to be able to turn on or off with #define at top, likewise debug serial prints.

    Forgot to mention, I switched back to using match instead of overflow. I could/should remove the test looking for it, ...

    Here is the run with it using pin pin
    Code:
    2(20001):  750.05  1500.05  2250.08  
    3(20000):  750.05  1500.05  2250.08  
    4(20001):  750.05  1500.05  2250.08  
    5(20000):  750.05  1500.05  2250.08  
    6(20001):  750.05  1500.05  2250.08
    Which is matching pretty well my 750, 1500, 2250 I passed in to output...
    Attached Files Attached Files

  12. #87
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    I am trying out several of the IO pins to see if they work for input: Currently driving by pin 9, will reviers to see.
    Working: 6, 10, 11, 12, 13, 14, 15, 19
    Not Working: 18, need to double check MUX setting.
    9 Works with 19 output

    18 Fixed (MUX 0 not 1) - I commented out test for overflow...
    Attached Files Attached Files

  13. #88
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    If I were going to make another pass in this, one thing I would double check is we set the list table value to this, before we enable interrupts as to make sure we have it set before any possible time the ISRs are called... Also I might add in a little robustness.

    My thoughts are currently have it like:
    Code:
    void PulsePositionBase::isrTimer1()
    {
    	DBGdigitalWriteFast(2, HIGH);
    	if (list[2] && TimerCHInPending(&IMXRT_TMR1.CH[0])) { list[2]->isr();}
    	if (list[3] && TimerCHInPending(&IMXRT_TMR1.CH[2])) { list[3]->isr();}
    	if (list[4] && TimerCHInPending(&IMXRT_TMR1.CH[1])) { list[4]->isr();}
    	asm volatile ("dsb");  // wait for clear  memory barrier
    	DBGdigitalWriteFast(2, LOW);
    }
    But am thinking to make TimerCHInPending be a member function of base (probably inline), maybe called more like:
    processTimerCHInPending and pass in the list item number like:
    My thoughts are currently have it like:
    Code:
    void PulsePositionBase::isrTimer1()
    {
    	DBGdigitalWriteFast(2, HIGH);
    	processTimerCHInPending(2, &IMXRT_TMR1.CH[0]);
    	processTimerCHInPending(3, &IMXRT_TMR1.CH[2]);
    	processTimerCHInPending(4, &IMXRT_TMR1.CH[1]);
    	asm volatile ("dsb");  // wait for clear  memory barrier
    	DBGdigitalWriteFast(2, LOW);
    }
    Where the process function, would do sort like the helper function does now, and IF it thinks there is an active interrupt pending on that channel, it would then check to see if list[n] is set and call it, else it would clear out those interrupt bits, as to not get called again and hang...

    Make sense. I will be off for awhile, so if someone beats me to it...

    Kurt

    EDIT: Done:
    Attached Files Attached Files
    Last edited by KurtE; 10-29-2019 at 05:22 PM.

  14. #89
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,236
    Quote Originally Posted by manitou View Post
    I was never able to get overflow (TOF) interrupt to work on T4 quad timer, so I used timer compare (0xffff) to count timer overflows.
    Just for the record, NXP discussion confirms bug in quad timer overflow interrupt -- though it does fire if counting down. Should be documented in latest errata.

  15. #90
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE

    Wow - I just back on the computer and its all done

    Just did a couple of tests. (1) using 2 T4's all pins are receiving and transmitting (only tested 3 really)… The receive pins are receiving the correct data and match the format that we would expect from a T3.x

    The second test was more fun. Loopback using 3 output pins and 3 receive pins. Bottom line SUCCESS - you solved the puzzle!
    Code:
    1941 :  600.08  1500.05  759.28  1500.05  1500.05  1234.61  
    1942 :  634.59  
    1942 :  2234.64  1500.05  1029.23  
    1942 :  600.08  1500.05  759.28  1500.05  1500.05  1234.61  
    1943 :  634.59  
    1943 :  2234.64  1500.05  1029.23  
    1943 :  600.08  1500.05  759.28  1500.05  1500.05  1234.61  
    1944 :  634.59  
    1944 :  2234.64  1500.05  1029.23  
    1944 :  600.08  1500.05  759.28  1500.05  1500.05  1234.61
    Heres the sketch if you want to play:
    Code:
    #include <PulsePosition_t4.h>
    
    PulsePositionInput myIn;
    PulsePositionOutput myOut;
    PulsePositionOutput myOut1;
    PulsePositionOutput myOut2;
    PulsePositionInput myIn1;
    PulsePositionInput myIn2;
    
    void setup() {
      myIn.begin(19);
      myIn1.begin(18);
      myIn2.begin(15);
      
      Serial.begin(115200);
      delay(2000);
      myOut.begin(13);
      myOut1.begin(6);
      myOut2.begin(11);
    
      myOut.write(1, 600.03);
      myOut.write(2, 1500);
      myOut.write(3, 759.24);
      // slots 4 and 5 will default to 1500 us
      myOut.write(6, 1234.56);
      myOut1.write(1, 2234.56);
      myOut1.write(3, 1029.19);
      myOut2.write(1, 634.56);
    
    }
    
    void loop() {
      int i, num;
      static int count = 0;
      int i1, num1;
      static int count1 = 0;
       int i2, num2;
      static int count2 = 0;
    
      
      // Every time new data arrives, simply print it
      // to the Arduino Serial Monitor.
      num = myIn.available();
      if (num > 0) {
        count = count + 1;
        Serial.print(count);
        Serial.print(" :  ");
        for (i=1; i <= num; i++) {
          float val = myIn.read(i);
          Serial.print(val);
          Serial.print("  ");
        }
        Serial.println();
      }
    
      num1 = myIn1.available();
      if (num1 > 0) {
        count1 = count1 + 1;
        Serial.print(count1);
        Serial.print(" :  ");
        for (i=1; i <= num1; i++) {
          float val1 = myIn1.read(i);
          Serial.print(val1);
          Serial.print("  ");
        }
        Serial.println();
      }
    
      num2 = myIn2.available();
      if (num1 > 0) {
        count2 = count2 + 1;
        Serial.print(count2);
        Serial.print(" :  ");
        for (i=1; i <= num2; i++) {
          float val2 = myIn2.read(i);
          Serial.print(val2);
          Serial.print("  ");
        }
        Serial.println();
      }
    }
    So which way do we want to go now - merge this pulse position or keep a separate T4 library?

  16. #91
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    Quote Originally Posted by manitou View Post
    Just for the record, NXP discussion confirms bug in quad timer overflow interrupt -- though it does fire if counting down. Should be documented in latest errata.
    Well that's 2 major things that are errors within the 1060! This and flexcan-FD FIFO.

    At least we know it wasn't something we all were doing wrong.

  17. #92
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,236
    Quote Originally Posted by mjs513 View Post

    So which way do we want to go now - merge this pulse position or keep a separate T4 library?
    You could fix framepin support. In my test sketch, I just used digitalWrite/digitalRead to implement framepin.
    https://forum.pjrc.com/threads/57894...l=1#post220044

  18. #93
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    Quote Originally Posted by manitou View Post
    You could fix framepin support. In my test sketch, I just used digitalWrite/digitalRead to implement framepin.
    https://forum.pjrc.com/threads/57894...l=1#post220044
    Shoot - forgot about that we everything else going on - working it now.

    EDIT: Done:

    PulsePosition_t4.zip

    Still have to test but off for an errand now will do when I get back.
    Last edited by mjs513; 10-29-2019 at 08:55 PM.

  19. #94
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    Quote Originally Posted by mjs513 View Post
    So which way do we want to go now - merge this pulse position or keep a separate T4 library?
    If it were me, I think I would do a half combine

    That is, I think I might do something like:

    Actually in both cases, would tend to do all of the normal library header stuff like in both header files.

    #ifndef __PULSE_POSITION_IN_H__
    #define __PULSE_POSITION_IN_H__
    .....
    #endif

    I would then edit PulsePosition.h file and maybe start off with something like:

    Code:
    #ifdef __AVR__
    #error "Sorry, PulsePosition does not work on Teensy 2.0 and other AVR-based boards"
    #elif defined(__IMXRT1062__)
    #include "PulsePosition_t4.h"
    #else 
    ..... all current stuff 
    
    #endif
    And then in PulsePositioin_t4.h and .cpp bracket the whole file with:
    Code:
    #if defined(__IMXRT1062__)
    .....
    #endif
    This is sort of what Paul did in wire library, where there are files split off WireKinetis and WireIMXRT

    Edit: Actually maybe the files should be renamed like: PulsePositionIMXRT.h like wire...

  20. #95
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE
    Will go the route u suggest, better that way.

    Have a couple more tests to run
    (1) frame pin and
    (2).rising and falling for polarity

    Know polarity works for tx cause I had a scope on the pins this morning, early morning.

  21. #96
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE - @manitou ….

    Just finished testing. Had a slight bug for implementing framePin but all is good now. Want to change digitalWrites to digitalWriteFast for final version.

    Also I just noted that when input is set to RISING or FALLING it doesn't matter to output capture. Will capture either on rising or falling edge.....

  22. #97
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    UPDATE:

    Incorporated the changes into the pulseposition main lib using the approach that @KurtE suggested. Gave it a quick spin and test using the loopback example with no problem. I issued a PR to @Paul:

    Updated PulsePosition Lib to support T4 #7

    The local fork on GITHUB for updated lib is at: https://github.com/mjs513/PulsePosition if you all want to give it a try.

  23. #98
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,236
    @mjs513 @KurtE
    Using your latest zip from this thread, I ran various tests with T4 loopback and data from T3.2 PulsePosition. All looks good. Impressive work managing all the ISRs!!

    Re: down counting and overflow interrupt
    As noted, though the quad timer overflow interrupt does NOT work when counting up, it does fire when counting down (DIR). FWIW, I made another version of my ppminq.ino sketch to count down and use the TOF interrupt rather than compare interrupt. Also complemented saved capture value so the saved values are counting up. Here is summary of changes for PPM Input
    Code:
    Change to initialize overflow interrupt instead of compare
    >   TMR1_SCTRL2 |= TMR_SCTRL_TOFIE;  // enable oflow interrupt
    
    change start up config to down count and no LENGTH
    >   TMR1_CTRL2 =  TMR_CTRL_DIR | TMR_CTRL_CM(1) | TMR_CTRL_PCS(8 + 2) | TMR_CTRL_SCS(2); // prescale
    
    In isr replace compare logic with overflow logic
    > void my_isr() {  // capture and underflow
    >   if (TMR1_SCTRL2 & TMR_SCTRL_TOF) { // underflow rollover
    >     TMR1_SCTRL2 &= ~(TMR_SCTRL_TOF);  // clear
    
    and in isr, flip bits when saving captured value
    >     val = (uint16_t)~(TMR1_CAPT2);   // count up
    I don't know if using the overflow interrupt rather than the compare interrupt would have simplified your ISR management.
    Last edited by manitou; 10-30-2019 at 02:30 PM.

  24. #99
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,712
    Hi @mjs513 and others... Good morning. Great stuff.

    Wondering if it would be a good idea to update the Readme.md file as part of this... Still back in the ice age that only mentions Teensy 3.1

    I did a quick and dirty update which is up in my branch: https://github.com/KurtE/PulsePosition/tree/readme

    Which has the contents:
    Code:
    PulsePosition
    =============
    
    Multiple High-Res Input &amp; Output PPM Encoded Signal Streams on Teensy 3.x, LC, and 4.0
    
    Valid pins (input or output) by board type:
    ```
    Teensy 3.6, 3.5:  5, 6, 9, 10, 20, 21, 22, 23
    Teensy 3.2, 3.1:  5, 6, 9, 10, 20, 21, 22, 23
    Teensy LC:        6, 9, 10, 20, 22, 23
    Teensy 4.0:       6, 9, 10, 11, 12, 13, 14, 15, 18, 19
    ```
    http://www.pjrc.com/teensy/td_libs_PulsePosition.html
    Could potentially add additional information.
    @Paul: Also note: The referred to html file needs updates as well to mention 4.0 and (8 pins versus 10...)

  25. #100
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,291
    @KurtE - @manitou

    @KurtE - I went ahead and updated the Readme with the added info to match what you have in your readme which is a good idea.

    @manitou - very cool that you got down counting and overflow interrupt working.

    @Paul - besides PulsePosition you are gong to have to update FreqMeas lib as well to show that pin 9 is used for input.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •