T4 Comparators and XBAR

Status
Not open for further replies.

TelephoneBill

Well-known member
From the R.M. page 291, the only analog comparator OUTs to appear on T4 pins directly are ACMP3_OUT (GPIO_AD_B1_14) on Pin26, and ACMP4_OUT (GPIO_AD_B1_15) on pin27. These are pins both on the underside and require soldering for connection.

But I did notice on page 3357 that ACMP1..4 are inputs to XBAR1. I wondered if it may be possible to route one of the ACMPx_OUT through the XBAR to then come out on a topside T4 pin. The XBAR is a bit of a mystery to use, so any help here would be very much appreciated.
 
Thanks for the reference. Had a look at the .ino, but quickly out of my depth with your code...

I think I know how the XBAR now works (maybe). But I'm stuck on being able to set a register on page 3367/3368. The register is called XBARAx_SEL3 and in my case "x" equals 1. The lowest 7 bits are called SEL6 and I think I need to put "28" (dec) = 0x001C into the register - that will specify the XBAR1 input (for XBAR1_OUT6) to be XBAR1_IN28 (which is ACMP3_OUT).

I attempted to find a label for that register in iMXRT.h, but the nearest I could find was "#define IOMUXC_XBAR1_IN03_SELECT_INPUT". I'm not convinced this is correct because the address of my register needs to be "403B_C000h base + 6h offset", where as the .h file states an address at (IMXRT_IOMUXC_b.offset210) - quite a bit different.

Page 315 also shows XBAR1 (XBAR_INOUT06) can be muxed to GPIO_EMC_04 with ALT3. I think this then connects XBAR1_OUT6 to T4 Pin 2.

So my code (which did not work) then was:

Code:
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);  //turn clock on for xbara1
  IOMUXC_XBAR1_IN03_SELECT_INPUT = 0x001C;    //This connects XBAR1_INOUT6 to XBAR1_IN28 (ACMP3_OUT)
  IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04 = 3;      //ALT3 connects T4 Pin 2 to XBAR1_INOUT6
  CCM_CCGR3 |= 0x03000000;                    //enable clocks to CG12 of CGR3 for ACMP3
  CMP3_CR0 = 0b00000000;                      // FILTER_CNT=0; HYSTCTR=0
  CMP3_CR1 = 0b00010111;                      // SE=0, high power, COUTA, output pin, enable; mode #2A
  CMP3_DACCR = 0b11011111;                    //Set DAC = 1/2 of VIN2 (3.3v) 
  CMP3_MUXCR = 0b00000111;                    //CMP_MUX_PSEL(0) | CMP_MUX_MSEL(7) Input pins select; plus = IN0 (pin 18), minus = DAC (code 7). PSTM = 0 (Pass Through Mode Disabled)

It appears that T4 Pin18 (AD_B1_01) is the default for all the ACMPx_IN0 inputs (including ACMP3_IN0), so no extra code required. My test was then to put a 10 turn pot (3v3 and GND) with wiper mid way and wiggle it about, looking for a switch of logic state on the Pin2 output. But sadly, it failed.

Can your good self (or anyone) spot a mistake?
 
Last edited:
Inspection again of the iMXTR.h file, I found there is a symbol for the XBARA1_SEL3 register after all. It has the correct address of "403B_C000h base + 6h offset". I was looking for XBAR1 (sometimes the manual uses XBARA1 and other times XBAR1).

Sadly, replacing line 2 above to read the following still did not work, so I'm persevering with experiments:

XBARA1_SEL3 = 0x001C; //This connects XBARA1_OUT6 to XBAR1_IN28 (ACMP3_OUT)
 
@TelephoneBill

Its been a long time since I played with the XBARA's to link to the encoder.

I think I know how the XBAR now works (maybe). But I'm stuck on being able to set a register on page 3367/3368. The register is called XBARAx_SEL3 and in my case "x" equals 1. The lowest 7 bits are called SEL6 and I think I need to put "28" (dec) = 0x001C into the register - that will specify the XBAR1 input (for XBAR1_OUT6) to be XBAR1_IN28 (which is ACMP3_OUT).
before I saw this I was looking at your code and what I did - hate getting old. Was going to say I think you missed the connection piece. There is a function I use that I stole from Paul that in pwm.c if I remember right that does that connection for you:
Code:
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
  // does not work, seems 8 bit access is not allowed
  volatile uint8_t *xbar = (volatile uint8_t *)XBARA1_SEL0;
  xbar[output] = input;
#endif
}

The way its used is:
Code:
xbar_connect(xbara1_IO[pin], 66);

now for me with the encoders the 66 represented the connection to the encoder
Code:
kXBARA1_OutputEnc1PhaseAInput   = 66|0x100U,   // XBARA1_OUT66 output assigned to ENC1_PHASE_A_INPUT

if I go back to the SDK (its in the manual somewhere too) I found this;
Code:
   kXBARB2_InputAcmp1Out           = 6|0x200U,    /**< ACMP1_OUT output assigned to XBARB2_IN6 input. */
    kXBARB2_InputAcmp2Out           = 7|0x200U,    /**< ACMP2_OUT output assigned to XBARB2_IN7 input. */
    kXBARB2_InputAcmp3Out           = 8|0x200U,    /**< ACMP3_OUT output assigned to XBARB2_IN8 input. */
    kXBARB2_InputAcmp4Out           = 9|0x200U,    /**< ACMP4_OUT output
so looking at this its telling me acmp3_out is really assigned to XBARA2_IN8? You can check the manual - maybe I am wrong.

Here is .h file from the sdk that I have been using for reference:
View attachment MIMXRT1052.zip
 
Many thanks again buddy. I can confirm all is now well. Your "xbar_connect" routine has confirmed that I was on the right track... the following line does exactly what your routine does. It is a complicated set of registers, but page 3367 explains fully when read very carefully (and the value 0x001C is GOOD for XBAR_IN28)...

XBARA1_SEL3 = 0x001C; //This connects XBARA1_OUT6 to XBAR1_IN28 (ACMP3_OUT)

But your response gave me inspiration... to go back and see if anything else might be needed. I re-read the IOMUXC page 289 (for T4 Pin 18) and page 315 (for T4 Pin 2) and that was when the "penny" dropped. A little note explained that there was yet another set of registers called IOMUXC_GPR_GPRx (where x is 6 in my case) and these registers define the "I/O direction" of T4 Pin 2. It will be an "input" if a bit is zero, and an output if the same bit is set to one. So with yet another 32 bit "or" of IOMUXC_GPR_GPRx with bit 18 set to "1" and Bob was my uncle (the binary rep makes sure I hit the right bit :eek: ).

I now have a 60 KHz sine wave (2 volts pk-pk) coming into Pin 18 via a 0.1mfd capacitor (biased to midpoint voltage with my 10 turn 10K pot strung across 3v3 and GND) and I have a beautiful 60 KHz square wave coming out of Pin 2. What a delight !! And that's thanks to teamwork.

Code:
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);  //turn clock on for xbara1
  XBARA1_SEL3 = 0x001C;                       //This connects XBAR1_OUT6 to XBAR1_IN28 (ACMP3_OUT)
  IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04 = 3;      //ALT3 connects XBAR1_INOUT6 to T4 Pin 2
  IOMUXC_GPR_GPR6 |= 0b00000000000001000000000000000000; //IOMUXC_XBAR_DIR_SEL_6 = 1 (direction select for XBAR_INOUT6)
  CCM_CCGR3 |= 0x03000000;                    //enable clocks to CG12 of CGR3 for ACMP3
  CMP3_CR0 = 0b00000000;                      //FILTER_CNT=0; HYSTCTR=0
  CMP3_CR1 = 0b00010111;                      //SE=0, high power, COUTA, output pin, enable; mode #2A
  CMP3_DACCR = 0b11011111;                    //Set DAC = 1/2 of VIN2 (3.3v) 
  CMP3_MUXCR = 0b00000111;                    //CMP_MUX_PSEL(0) | CMP_MUX_MSEL(7) Input pins select; plus = IN0 (pin 18), minus = DAC (code 7). PSTM = 0 (Pass Through Mode Disabled)
 
@TelephoneBill

Really glad you got it working. The encoder setup was a little more involved since it used most of the XBAR pins. Beginning to remember a bit of what I did. If you go back through the thread you can see all the help I got on getting it working :)

Glad I was able to help a little bit. Wish I could have helped more. That RM always gave me headaches - like you had to read and reread it several times before things clicked.

Can't wait to see what you do with all the stuff you are doing with the ADC.

Mike
 
Status
Not open for further replies.
Back
Top