SMPTE timedode (LTC) decode library for mbed
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/
Diff: LTC_SMPTE.cpp
- 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, <C_SMPTE::isr_change); - _input.rise(this, <C_SMPTE::isr_change); - _timer.start(); + this->type = type; + if (type == LTC_INPUT) { + _input = new InterruptIn(pin); + _input->mode(PullUp); + _input->fall(this, <C_SMPTE::isr_change); + _input->rise(this, <C_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; }