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);