SMPTE timedode (LTC) decode library for mbed

Dependents:   LTC_SMPTE_sample

SMPTE timedode (LTC) decode library

SMPTEタイムコードをデコード(受信)・エンコード(送信)するライブラリです。

平衡/不平衡/サウンド等によるLTC信号は、適当な回路で整形して入力してください。
出力は適当なドライバ回路を設けてください。

簡易的なプログラムのため、細かいフラグなどは無視しています。

LPC1768 専用、Timer 2 を占有します。

Sample

Import programLTC_SMPTE_sample

SMPTE timedode (LTC) decode library for mbed https://developer.mbed.org/users/okini3939/code/LTC_SMPTE/

Revision:
1:63ceee4bfd05
Parent:
0:8d19e2158eb4
Child:
2:13a89fffbb75
--- a/LTC_SMPTE.cpp	Mon Nov 16 12:51:43 2015 +0000
+++ b/LTC_SMPTE.cpp	Fri Apr 13 04:05:13 2018 +0000
@@ -9,6 +9,10 @@
 
 #include "LTC_SMPTE.h"
 
+#if ! defined(TARGET_LPC176X)
+#error "this CPU is not supported. use LPC1768"
+#endif
+
 // pulse width: 416.7us(30fps)
 // 80bit x 30frame/s --> 416.7us/bit
 #define ONE_TIME_MIN  100
@@ -16,18 +20,46 @@
 #define ZERO_TIME_MIN 300
 #define ZERO_TIME_MAX 500
 
-LTC_SMPTE::LTC_SMPTE (PinName input) : _input(input) {
+#define US_TICKER_TIMER      ((LPC_TIM_TypeDef *)LPC_TIM2_BASE)
+#define US_TICKER_TIMER_IRQn TIMER2_IRQn
+
+LTC_SMPTE *LTC_SMPTE::_inst;
 
+void isrTimer () {
+    US_TICKER_TIMER->TC = 0;
+    US_TICKER_TIMER->IR = 1;
+    LTC_SMPTE::_inst->isr_ticker();
+}
+
+LTC_SMPTE::LTC_SMPTE (PinName pin, enum LTC_TYPE type) {
+
+    _inst = this;
     mode = 0;
     count = 0;
     oneflg = 0;
     direction = 0;
     received = 0;
 
-    _input.mode(PullUp);
-    _input.fall(this, &LTC_SMPTE::isr_change);
-    _input.rise(this, &LTC_SMPTE::isr_change);
-    _timer.start();
+    this->type = type;
+    if (type == LTC_INPUT) {
+        _input = new InterruptIn(pin);
+        _input->mode(PullUp);
+        _input->fall(this, &LTC_SMPTE::isr_change);
+        _input->rise(this, &LTC_SMPTE::isr_change);
+
+        _timer.start();
+    } else {
+        _output = new DigitalOut(pin);
+
+        LPC_SC->PCONP |= 1 << 22; // Clock TIMER_2
+        US_TICKER_TIMER->CTCR = 0x0; // timer mode
+        uint32_t PCLK = SystemCoreClock / 4;
+        US_TICKER_TIMER->TCR = 0x2;  // reset
+        uint32_t prescale = PCLK / 2400 / 2; // 80bit * 30frame
+        US_TICKER_TIMER->PR = prescale - 1;
+        NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)&isrTimer);
+        NVIC_EnableIRQ(US_TICKER_TIMER_IRQn);
+    }
 }
 
 void LTC_SMPTE::isr_change () {
@@ -124,6 +156,96 @@
     received = 0;
 }
 
+void LTC_SMPTE::write (int hour, int min, int sec, int frame, int dir) {
+    if (type != LTC_OUTPUT) return;
+
+    US_TICKER_TIMER->TCR = 0;
+    this->hour = hour;
+    this->min = min;
+    this->sec = sec;
+    this->frame = frame;
+    this->direction = dir;
+    mode = 0;
+    count = 0;
+
+    US_TICKER_TIMER->TCR = 0x2;  // reset
+    // set match value
+    US_TICKER_TIMER->MR0 = 1;
+    // enable match interrupt
+    US_TICKER_TIMER->MCR |= 1;
+    US_TICKER_TIMER->TCR = 1; // enable = 1, reset = 0
+
+    _timer.reset();
+    _timer.start();
+    __enable_irq();
+}
+
+void LTC_SMPTE::isr_ticker () {
+    if (mode) {
+        if (bit) {
+            phase = !phase;
+            _output->write(phase);
+        }
+        mode = 0;
+        return;
+    }
+
+    phase = !phase;
+    _output->write(phase);
+    mode = 1;
+
+    if (count >= 0 && count <= 3) {
+        bit = (frame % 10) & (1 << count);
+    } else
+    if (count >= 8 && count <= 9) {
+        bit = (frame / 10) & (1 << (count - 8));
+    } else
+    if (count >= 16 && count <= 19) {
+        bit = (sec % 10) & (1 << (count - 16));
+    } else
+    if (count >= 24 && count <= 26) {
+        bit = (sec / 10) & (1 << (count - 24));
+    } else
+    if (count >= 32 && count <= 35) {
+        bit = (min % 10) & (1 << (count - 32));
+    } else
+    if (count >= 40 && count <= 42) {
+        bit = (min / 10) & (1 << (count - 40));
+    } else
+    if (count >= 48 && count <= 51) {
+        bit = (hour % 10) & (1 << (count - 48));
+    } else
+    if (count >= 56 && count <= 57) {
+        bit = (hour / 10) & (1 << (count - 56));
+    } else
+    if ((count >= 66 && count <= 77) || count == 79) {
+        bit = 1;
+    } else {
+        bit = 0;
+    }
+
+    count ++;
+    if (count >= 80) {
+        count = 0;
+        frame ++;
+        if (frame >= 30) {
+            frame = 0;
+            sec ++;
+            if (sec >= 60) {
+                sec = 0;
+                min ++;
+                if (min >= 60) {
+                    min = 0;
+                    hour ++;
+                    if (hour >= 24) {
+                        hour = 0;
+                    }
+                }
+            }
+        }
+    }
+}
+
 int LTC_SMPTE::isReceived () {
     return received;
 }