Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Wire.h>
- #include <LiquidCrystal.h>
- #include <MIDI.h>
- LiquidCrystal lcd (8, 9, 4, 5, 6, 7);
- #define icpPin 49 // ICP input pin on arduino // not 8
- unsigned int zero_time_max = 1000;
- unsigned int one_time_max = zero_time_max / 2;
- unsigned int zero_time_min = zero_time_max * 0.75;
- unsigned int one_time_min = one_time_max * 0.75;
- #define end_data_position 63
- #define end_sync_position 77
- #define end_smpte_position 80
- volatile unsigned int bit_time;
- volatile boolean valid_tc_word;
- volatile boolean ones_bit_count;
- volatile boolean tc_sync;
- volatile boolean write_tc_out;
- volatile boolean drop_frame_flag;
- volatile byte total_bits;
- volatile byte current_bit;
- volatile byte sync_count;
- volatile byte tc[8];
- char timeCode[12];
- char userBit[11];
- static byte toSend;
- byte h, m, s, f;
- byte MTCIndex = 0;
- MIDI_CREATE_DEFAULT_INSTANCE();
- long runningAverage(int M) {
- #define LM_SIZE 64
- static int LM[LM_SIZE]; // LastMeasurements
- static byte index = 0;
- static long sum = 0;
- static byte count = 0;
- // keep sum updated to improve speed.
- sum -= LM[index];
- LM[index] = M;
- sum += LM[index];
- index++;
- index = index % LM_SIZE;
- if (count < LM_SIZE) count++;
- return sum / count;
- }
- int i = 0;
- volatile byte j = 0;
- volatile byte k = 0;
- volatile byte oldF;
- ISR(TIMER5_COMPA_vect) {
- /*
- if (j++ > 24) {
- j = 0;
- k = 1 - k;
- if (k)
- digitalWrite(13, HIGH);
- else
- digitalWrite(13, LOW);
- }
- */
- if (f == 0) {
- k = 1 - k;
- if (k)
- digitalWrite(13, HIGH);
- else
- digitalWrite(13, LOW);
- }
- if (f==0 && f != oldF) {
- MTCIndex=0;
- }
- sendMTC();
- /*
- MIDI.sendNoteOn(i, i * 2, 1);
- if (i++ > 24)
- i = 0;
- */
- oldF=f;
- }
- /* ICR interrupt vector */
- ISR(TIMER4_CAPT_vect)
- {
- //toggleCaptureEdge
- TCCR4B ^= _BV(ICES4);
- bit_time = ICR4;
- //resetTimer1
- TCNT4 = 0;
- if ((bit_time < one_time_min) || (bit_time > zero_time_max)) // get rid of anything way outside the norm
- {
- total_bits = 0;
- }
- else
- {
- if (ones_bit_count == true) // only count the second ones pluse
- ones_bit_count = false;
- else
- {
- if (bit_time > zero_time_min)
- {
- current_bit = 0;
- sync_count = 0;
- }
- else //if (bit_time < one_time_max)
- {
- ones_bit_count = true;
- current_bit = 1;
- sync_count++;
- if (sync_count == 12) // part of the last two bytes of a timecode word
- {
- sync_count = 0;
- tc_sync = true;
- total_bits = end_sync_position;
- }
- }
- if (total_bits <= end_data_position) // timecode runs least to most so we need
- { // to shift things around
- tc[0] = tc[0] >> 1;
- for (int n = 1; n < 8; n++)
- {
- if (tc[n] & 1)
- tc[n - 1] |= 0x80;
- tc[n] = tc[n] >> 1;
- }
- if (current_bit == 1)
- tc[7] |= 0x80;
- }
- total_bits++;
- }
- if (total_bits == end_smpte_position) // we have the 80th bit
- {
- total_bits = 0;
- if (tc_sync)
- {
- tc_sync = false;
- valid_tc_word = true;
- }
- }
- if (valid_tc_word)
- {
- valid_tc_word = false;
- drop_frame_flag = bit_is_set(tc[1], 2);
- timeCode[11] = 0;
- timeCode[10] = (tc[0] & 0x0F) + 0x30; // frames
- timeCode[9] = (tc[1] & 0x03) + 0x30; // 10's of frames
- if (drop_frame_flag) {
- timeCode[8] = ';';
- } else {
- timeCode[8] = ':';
- }
- timeCode[7] = (tc[2] & 0x0F) + 0x30; // seconds
- timeCode[6] = (tc[3] & 0x07) + 0x30; // 10's of seconds
- timeCode[5] = ':';
- timeCode[4] = (tc[4] & 0x0F) + 0x30; // minutes
- timeCode[3] = (tc[5] & 0x07) + 0x30; // 10's of minutes
- timeCode[2] = ':';
- timeCode[1] = (tc[6] & 0x0F) + 0x30; // hours
- timeCode[0] = (tc[7] & 0x03) + 0x30; // 10's of hours
- h = (tc[6] & 0x0F) + (tc[7] & 0x03) * 10;
- m = (tc[4] & 0x0F) + (tc[5] & 0x07) * 10;
- s = (tc[2] & 0x0F) + (tc[3] & 0x07) * 10;
- f = (tc[0] & 0x0F) + (tc[1] & 0x03) * 10;
- userBit[10] = 0;
- userBit[9] = ((tc[0] & 0xF0) >> 4) + 0x30; // user bits 8
- userBit[8] = ((tc[1] & 0xF0) >> 4) + 0x30; // user bits 7
- userBit[7] = ((tc[2] & 0xF0) >> 4) + 0x30; // user bits 6
- userBit[6] = ((tc[3] & 0xF0) >> 4) + 0x30; // user bits 5
- userBit[5] = '-';
- userBit[4] = ((tc[4] & 0xF0) >> 4) + 0x30; // user bits 4
- userBit[3] = ((tc[5] & 0xF0) >> 4) + 0x30; // user bits 3
- userBit[2] = '-';
- userBit[1] = ((tc[6] & 0xF0) >> 4) + 0x30; // user bits 2
- userBit[0] = ((tc[7] & 0xF0) >> 4) + 0x30; // user bits 1
- write_tc_out = true;
- }
- }
- }
- void setup()
- {
- noInterrupts();
- pinMode(13, OUTPUT);
- lcd.begin(16, 2);
- //lcd.setCursor(0, 1);
- //lcd.print("hello timecody");
- // beginSerial (115200);
- //pinMode(icpPin, INPUT); // ICP pin (digital pin 8 on arduino) as input
- bit_time = 0;
- valid_tc_word = false;
- ones_bit_count = false;
- tc_sync = false;
- write_tc_out = false;
- drop_frame_flag = false;
- total_bits = 0;
- current_bit = 0;
- sync_count = 0;
- //Serial.println("Finished setup ");
- delay (1000);
- // TIMER 4 - DECODE SMPTE LTC
- TCCR4A = B00000000; // clear all
- TCCR4B = B11000010; // ICNC4 noise reduction + ICES4 start on rising edge + CS11 divide by 8
- TCCR4C = B00000000; // clear all
- TIMSK4 = B00100000; // ICIE4 enable the icp
- TCNT4 = 0; // clear timer4
- // TIMER 5 - SYNCHRONIZE ON QUARTER FRAMES
- TCCR5A = B00000000; // clear all
- TCCR5B = B00000101; // CS11 divide by 64
- TCCR5C = B00000000; // clear all
- TIMSK5 = B00000010; // OCIE5A ENABLE.
- TCNT5 = 0;
- OCR5A = 65535; // clear timer5
- interrupts();
- MIDI.begin(MIDI_CHANNEL_OMNI);
- }
- /* send MIDI Timecode Quarter Frame*/
- void sendMTC() {
- switch (MTCIndex)
- {
- case 0:
- toSend = ((f & 0xF));
- break;
- case 1:
- toSend = (((f & 0xF0) >> 4));
- break;
- case 2:
- toSend = ((s & 0xF));
- break;
- case 3:
- toSend = (((s & 0xF0) >> 4));
- break;
- case 4:
- toSend = ((m & 0xF));
- break;
- case 5:
- toSend = (((m & 0xF0) >> 4));
- break;
- case 6:
- toSend = ((h & 0xF));
- break;
- case 7:
- toSend = (((h & 0xF0) >> 4 )); // 0x70 = 24 fps // 0x72 = 25 fps // 0x74 = 30df fps // 0x76 = 30 fps
- break;
- }
- MIDI.sendTimeCodeQuarterFrame(MTCIndex++, toSend);
- if (MTCIndex > 7)
- MTCIndex = 0;
- }
- int kk = 1;
- void loop()
- {
- if (write_tc_out)
- {
- write_tc_out = false;
- /*
- We are polling TCNT5 (Timer 5 Counter) every time a frame comes past.
- Each time we see a value, we are going to grab a running average and then
- divide the value by 4. This is the timing interval we will use for
- delivery of MTC Quarter Frames.
- */
- OCR5A = runningAverage(TCNT5) / 4; //
- TCNT5 = 0;
- lcd.setCursor(11, 1);
- lcd.print(" ");
- lcd.setCursor(11, 1);
- lcd.print(OCR5A);
- lcd.setCursor(0, 0);
- lcd.print(timeCode);
- lcd.setCursor(0, 1);
- lcd.print(userBit);
- if (f == 0) {
- MTCIndex = 0;
- if (kk) {
- j = 0;
- kk = 0;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement