How to implement a 2MHz 20bit protocol on Teensy 4.0?

Status
Not open for further replies.

DanielO

Member
I need to implement a protocol which require 8pins to output 20 bits of data in sync each cycle. The protocol is called XY2-100 and operates at 2MHz.

How do i write the pins simultaneousy?


Some detail:

I had a (almost) working solution on Teensy 3.6 but my code was to slow resulting in communication errors. I never got around to optimize more and since my knowledge is very limited most of the code is inspired by others and modified... :p

Now i want to get it working and i have high hopes with the performance boost of the teensy 4.0. So i tried compiling for T4 but got some errors which i do not completly understand other than i might have been using an inefficient way of solving my problem and adressing and setting up HW does not work the same on T4 as on th T3.6.

Code:
int pwm_pin_sync = 14;   // PORT D1
int pwm_pin_sync_inv = 6;   // PORT D1
int pwm_pin_clock = 18;  // PORT B0  (18 Teensy 4.0 / 16 Teensy 3.6)
int pwm_pin_dataX = 7;   // PORT D2 Chan 1+
int pwm_pin_dataX2 = 1; // PORT D6  (1 Teensy 4.0 / 21 Teensy 3.6)
int pwm_pin_dataY = 8;   // PORT D3
int pwm_pin_dataY2 = 0; // PORT D5  (0 Teensy 4.0 / 20 Teensy 3.6)



Code:
void init_pwm(int khz) {
  //pwm_pin_clock
  // T3.6  CORE_PIN16_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; // enable PWM
 CORE_PIN18_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; // enable PWM
  FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE;
}

and in setup:

Code:
  pinMode(pwm_pin_dataX, OUTPUT);
  pinMode(pwm_pin_dataY, OUTPUT);
  pinMode(pwm_pin_dataX2, OUTPUT);
  pinMode(pwm_pin_dataY2, OUTPUT);
  pinMode(pwm_pin_clock, OUTPUT);
  pinMode(pwm_pin_sync, OUTPUT);
  pinMode(pwm_pin_sync_inv, OUTPUT);
  pinMode(LASER_TTL_PIN, OUTPUT);
  
  ARM_DEMCR |= ARM_DEMCR_TRCENA;
  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
 
  init_pwm(2000);

  analogWriteFrequency(pwm_pin_clock, 200e4); // ~1usec period //YELLOW
  analogWrite(pwm_pin_clock, 32768); // 50% duty for 16-bit range

  FTM0_SYNC = 1;
  FTM1_SYNC = 1;
  FTM2_SYNC = 1;

  attachInterrupt(digitalPinToInterrupt(pwm_pin_clock), data, FALLING);
  
#endif

And while running write the data like below:

Code:
void data()
{
//  if(hasData != 0)
//  {
    uint32_t d = 2UL;

    //WRITE SIGNAL
    cbitx = activePacketX[bitCount];
    cbity = activePacketY[bitCount];
    d = (d & ~(1UL << 3)) | (cbity << 3); //PORT D3 --> pin8
    d = (d & ~(1UL << 2)) | (cbitx << 2);  //PORT D2 --> pin7

    // WRITE INVERSE SIGNAL
    d = (d & ~(1UL << 5)) | ((!cbity) << 5); //PORT D5 --> pin0
    d = (d & ~(1UL << 6)) | ((!cbitx) << 6);  //PORT D6 --> pin1

    //WRITE SYNC
    if(bitCount >= 19)
    {
      hasData = 0;
      bitCount = -1;
      d = (d & ~(1UL << 1)) | (0 << 1);   // PORT D1 --> pin 14
      d = (d & ~(1UL << 1)) | (1 << 4);   // PORT D4 --> pin 6
    }
    
    GPIOD_PDOR = d;
    bitCount++;
//  }
}
 
Teensy 4.0 has completely different timers. The FTM timers are only in Teensy 3.2.

The good news is the FlexPWM timers in Teensy 4.0 have even more capability than the FTM ones Teensy 3.x had. The bad news is they have completely different registers and they've packed with so many features that it's quite a lot of info to read & understand. You can get the reference manual here:

https://www.pjrc.com/teensy/datasheets.html
 
Im trying to understand the purpose of the different timers but to me it would make sense to use PIT instead of GPT or TMR due to ease of use but i might be missing something.

I am looking for sample code but the supplied snippets in the manual say nothing to me....

Are there any samples of how to use?
 
Status
Not open for further replies.
Back
Top