Unable to output signal other than PORTB on Arduino 2560

Hello. I found this code on this forum. The code works, I get a signal on pins 52 and 53. But there is a problem, I use pin 53 for peripherals.

So I tried to output the signal to other pins.

// SMPTE Timecode Generator

/*
  PAL = 25FPS = 40ms per frame
  40ms / 80bits = 500us per bit
  250us per half bit
  
  LM1881 has ODD/EVEN output connected to INT0 (Pin 2)
*/
#define compareReg 3950                 // Timer1 compare value (tweak to be just over a half bit cycle)

#define continuous true                 // Set true if no LM1881 field interrupt available, will try to tune speed to 40ms per frame

// Timecode data
const uint8_t userBits[4] = {0x98,0x76,0x54,0x32};  // LSB on right (BCD) Reads nibbles backwards
volatile uint8_t frames = 24;
volatile uint8_t seconds = 59;
volatile uint8_t minutes = 59;
volatile uint8_t hours = 23;

volatile boolean tcRunning = false;     // Start/Stop TC output
boolean tcStopping = false;             // True when pending end to TC
boolean tcHalfBit = false;              // ISR is writing a first half bit if true
boolean currentBit;                     // Current bit being written. Used by ISR to speed up edge changes (true = 1, 0 = false)
uint8_t bitCount = 80;                  // Countdown bit counter used by ISR
uint8_t workTC[10];                     // The TC currently being output by the interrupt code

volatile uint16_t tcSpeed = compareReg;
volatile uint16_t tcTime = 0;
uint32_t tcStartTime = 0;

// Timer1 overflow interrupt service routine every 250us or just under
ISR(TIMER1_COMPA_vect){
  TCNT1 = 0;                            // Zero timer 1 count
  if(tcRunning){  
    tcHalfBit = !tcHalfBit;             // Flip the halfbit state
    if (tcHalfBit == true){             // First half bit (always flip at start of new bit)
      PORTB = PORTB ^ 0x03;             // Flip bits on PORTB
      if(tcStopping == true){           // Are we stopping?
        tcStopping = false;             // Reset ready for next time
        tcRunning = false;              // Stop us
        tcHalfBit = false;              // Next start will be a full bit
      } 
    } 
    else{                               // Half bit is false (second half of bit)
      if(currentBit == true){           // 1 bit so change half way
        PORTB = PORTB ^ 0x03;           // Flip bits on PORTB
      } 
      if(bitCount == 0){                // Last bit sent?
        if (continuous){
          tcTime = micros() - tcStartTime;// Calculate time
          tcStartTime = micros();       // Store current time
bitSet(PORTB,7);  // Test pin (LED)
          if (tcTime > 40000){          // If greater than 40ms
            tcSpeed--;                  // Reduce timer1 compare threshold
          }
          else{
            tcSpeed++;                  // Increment timer1 compare threshold
          }
          OCR1A = tcSpeed;              // And store it
        }
        else{
          tcStopping = true;            // Signal we are stopping
        }
        incTC();                        // Increment TC
        packTC();                       // Pack it ready for ISR
        bitCount = 80;                  // Preload bit counter
      }
      currentBit = bitRead(workTC[9],0);// Pre-read next bit
      shiftRight(workTC, sizeof(workTC));// Rotate buffer right
      bitCount--;                       // Decrement counter
    }
  }
bitClear(PORTB,7);  // Test pin (LED)
}

void setup(){
  Serial.begin(9200);
  
  pinMode(13, OUTPUT);                  // LED test pin (PB7 on MEGA)
  pinMode(52, OUTPUT);                  // TC Output (PB1 on MEGA)
  pinMode(53, OUTPUT);                  // TC Output (PB0 on MEGA)
  digitalWrite(52, LOW);                // Set LOW
  digitalWrite(53, HIGH);               // Set opposite to other

  Serial.println("Jamming...");
  setupTimer1();                        // Setup the ISR
  tcRunning = true;                     // Start TC running
}

void loop(){
  // while(tcRunning){};
  // tcRunning = true;                     // Start TC running
  delay(40);
  cli();
  uint16_t x = tcTime;
  sei();
  Serial.println(x);
  Serial.println(tcSpeed);
}

// Increment the timecode
void incTC(){
  frames++;                             // Increment frames
  if(frames > 24){
    frames = 0;
    seconds++;
  }
  if(seconds > 59){
    seconds = 0;
    minutes++;
  }
  if(minutes > 59){
    minutes = 0;
    hours++;
  }
  if(hours > 23){
    hours = 0;
  }
}
// Pack the timecode
void packTC(){
  uint8_t scratch1;
  uint8_t scratch2;
  
  scratch1 = dec2bcd(frames);
  scratch2 = userBits[3];
  workTC[9] = (scratch2 << 4) | (scratch1 & 0x0F);
  workTC[8] = (scratch2 & 0xF0) | ((scratch1 >> 4) & 0x03);
  
  scratch1 = dec2bcd(seconds);
  scratch2 = userBits[2];
  workTC[7] = (scratch2 << 4) | (scratch1 & 0x0F);
  workTC[6] = (scratch2 & 0xF0) | ((scratch1 >> 4) & 0x07);
  
  scratch1 = dec2bcd(minutes);
  scratch2 = userBits[1];
  workTC[5] = (scratch2 << 4) | (scratch1 & 0x0F);
  workTC[4] = (scratch2 & 0xF0) | ((scratch1 >> 4) & 0x07);
  
  scratch1 = dec2bcd(hours);
  scratch2 = userBits[0];
  workTC[3] = (scratch2 << 4) | (scratch1 & 0x0F);
  workTC[2] = (scratch2 & 0xF0) | ((scratch1 >> 4) & 0x03);
  
  workTC[1] = 0xFC;
  workTC[0] = 0xBF;
}
// Unpack TC
void unpackTC(){
  char tc[12] = {0};
  char ub[12] = {0};
  
  tc[0] = (workTC[2] & 0x03) + '0';                    // 10's of hours
  tc[1] = (workTC[3] & 0x0F) + '0';                    // hours
  tc[2] = ':';
  tc[3] = (workTC[4] & 0x07) + '0';                    // 10's of minutes
  tc[4] = (workTC[5] & 0x0F) + '0';                    // minutes
  tc[5] =  ':';
  tc[6] = (workTC[6] & 0x07) + '0';                    // 10's of seconds
  tc[7] = (workTC[7] & 0x0F) + '0';                    // seconds
  tc[8] =  '.';
  tc[9] = (workTC[8] & 0x03) + '0';                    // 10's of frames
  tc[10] = (workTC[9] & 0x0F) + '0';                   // frames
  
  ub[0] = ((workTC[9] & 0xF0) >> 4) + '0';             // user bits 1
  ub[1] = ((workTC[8] & 0xF0) >> 4) + '0';             // user bits 2
  ub[2] = '-';
  ub[3] = ((workTC[7] & 0xF0) >> 4) + '0';             // user bits 3
  ub[4] = ((workTC[6] & 0xF0) >> 4) + '0';             // user bits 4
  ub[5] = '-';
  ub[6] = ((workTC[5] & 0xF0) >> 4) + '0';             // user bits 5
  ub[7] = ((workTC[4] & 0xF0) >> 4) + '0';             // user bits 6
  ub[8] = '-';
  ub[9] = ((workTC[3] & 0xF0) >> 4) + '0';             // user bits 7
  ub[10] = ((workTC[2] & 0xF0) >> 4) + '0';            // user bits 8
  
  Serial.print(tc);
  Serial.print("\t");
  Serial.println(ub);
}

void setupTimer1(){
  cli();                                // Disable all interrupts
  packTC();                             // Load first timecode
  TCCR1A = 0;                           // Clear all flags in control register A
  TCCR1B = 0;                           // Clear all flags in control register B
  TCNT1 = 0;                            // Zero timer 1 count
  OCR1A = compareReg;                   // Preload compare match register
  // 1x prescaler
  bitClear(TCCR1B, CS12);
  bitClear(TCCR1B, CS11);
  bitSet(TCCR1B, CS10);
  bitSet(TIMSK1, OCIE1A);               // Enable timer compare interrupt
  sei();                                // enable all interrupts
}
// Convert decimal number to BCD
uint8_t dec2bcd(uint8_t n){
  //return ((n / 10) * 16) + (n % 10)
  uint16_t a = n;
  byte b = (a*103) >> 10;  // this equals:  b = a/10;
  return  n + b*6;
}

void shiftRight(uint8_t theArray[], uint8_t theArraySize){
  uint8_t x;
  for (x = theArraySize; x > 0; x--){
    uint8_t xBit = bitRead(theArray[x - 1], 0);
    theArray[x] = theArray[x] >> 1;
    theArray[x] = theArray[x] | (xBit << 7);
  }
  theArray[x] = theArray[x] >> 1;
}

I decided to use PORTC, I chose pins 30 and 31. But I get a completely different signal. Why is this happening?


PORTC = PORTC ^ 0x03; 

  pinMode(30, OUTPUT); 
  pinMode(31, OUTPUT);
  digitalWrite(30, LOW);
  digitalWrite(31, HIGH);

What do you mean by "completely different signal"?

What do you expect to happen with the XOR operation?

PORTC = PORTC ^ 0x03; 

Pins 30 and 31 appear to be assigned to PORTC, bits 7 and 6, respectively. The XOR above will affect PC0 and PC1, if at all.

The pin numbers run backwards in PORTC.

Thank you very much! Indeed, I was wrong. That's how it all worked

PORTC = PORTC ^ 0b11000000;

@Riva Hello. As far as I understand, you are the author of this code. I'm still trying to figure it out.

You asked not to write in private messages, so I'm asking the question here.

I can't figure out how you calculated compareReg. I'm trying to get my code to run at 24 FPS.

This is definitely related to the frequency of MEGA 2560 (16 MHz) and Prescaler=1 (CS10)

As far as I understand, the number should be less, because. there are fewer frames. Do you have the formula?

I cannot remember how I calculated the compareReg value (I don't even remember publishing the code) but it will be a higher value for 24FPS and not lower. From the current code

/*
  PAL = 25FPS = 40ms per frame
  40ms / 80bits = 500us per bit
  250us per half bit
*/

so

/*
  CINEMA = 24FPS = 41.7ms per frame
  41.7ms / 80bits = 521us per bit
  260us per half bit
*/
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.