SMPTE timedode (LTC) decode library for mbed
Embed:
(wiki syntax)
Show/hide line numbers
LTC_SMPTE.cpp
Go to the documentation of this file.
00001 /** 00002 * SMPTE timedode (LTC) decode library for mbed 00003 * Copyright (c) 2015 Suga 00004 * Released under the MIT License: http://mbed.org/license/mit 00005 */ 00006 /** @file 00007 * @brief SMPTE timedode (LTC) decode library for mbed 00008 */ 00009 00010 #include "LTC_SMPTE.h" 00011 00012 #if ! defined(TARGET_LPC176X) 00013 #error "this CPU is not supported. use LPC1768" 00014 #endif 00015 00016 // pulse width: 416.7us(30fps) 00017 // 80bit x 30frame/s --> 416.7us/bit 00018 #define ONE_TIME_MIN 180 00019 #define ONE_TIME_MAX 280 00020 #define ZERO_TIME_MIN 390 00021 #define ZERO_TIME_MAX 540 00022 00023 #define FPS24_REF 521 00024 #define FPS25_REF 500 00025 #define FPS30_REF 417 00026 00027 #define US_TICKER_TIMER ((LPC_TIM_TypeDef *)LPC_TIM2_BASE) 00028 #define US_TICKER_TIMER_IRQn TIMER2_IRQn 00029 00030 LTC_SMPTE *LTC_SMPTE::_inst; 00031 00032 void isrTimer () { 00033 US_TICKER_TIMER->TC = 0; 00034 US_TICKER_TIMER->IR = 1; 00035 LTC_SMPTE::_inst->isr_ticker(); 00036 } 00037 00038 LTC_SMPTE::LTC_SMPTE (PinName pin, enum LTC_TYPE type) { 00039 00040 _inst = this; 00041 mode = 0; 00042 count = 0; 00043 oneflg = 0; 00044 direction = 0; 00045 received = 0; 00046 00047 this->type = type; 00048 if (type == LTC_INPUT) { 00049 _input = new InterruptIn(pin); 00050 _input->mode(PullUp); 00051 _input->fall(this, <C_SMPTE::isr_change); 00052 _input->rise(this, <C_SMPTE::isr_change); 00053 00054 _timer.start(); 00055 } else { 00056 _output = new DigitalOut(pin); 00057 00058 LPC_SC->PCONP |= 1 << 22; // Clock TIMER_2 00059 US_TICKER_TIMER->CTCR = 0x0; // timer mode 00060 uint32_t PCLK = SystemCoreClock / 4; 00061 US_TICKER_TIMER->TCR = 0x2; // reset 00062 uint32_t prescale = PCLK / 2400 / 2; // 80bit * 30frame 00063 US_TICKER_TIMER->PR = prescale - 1; 00064 NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)&isrTimer); 00065 NVIC_EnableIRQ(US_TICKER_TIMER_IRQn); 00066 } 00067 } 00068 00069 void LTC_SMPTE::isr_change () { 00070 int b, t; 00071 00072 t = _timer.read_us(); 00073 _timer.reset(); 00074 00075 if (t >= ONE_TIME_MIN && t < ONE_TIME_MAX) { 00076 if (oneflg == 0) { 00077 oneflg = 1; 00078 return; 00079 } else { 00080 oneflg = 0; 00081 b = 1; 00082 } 00083 } else 00084 if (t >= ZERO_TIME_MIN && t < ZERO_TIME_MAX) { 00085 oneflg = 0; 00086 b = 0; 00087 00088 if (t >= FPS24_REF - 10 && t <= FPS24_REF + 10) { 00089 fps = 0; 00090 } else 00091 if (t >= FPS25_REF - 10 && t <= FPS25_REF + 10) { 00092 fps = 1; 00093 } else 00094 if (t >= FPS30_REF - 10 && t <= FPS30_REF + 10) { 00095 fps = drop ? 2 : 3; // 29.97 / 30 00096 } 00097 } else { 00098 oneflg = 0; 00099 count = 0; 00100 return; 00101 } 00102 00103 for (int i = 0; i < 9; i ++) { 00104 code[i] = (code[i] >> 1) | ((code[i + 1] & 1) ? 0x80 : 0); 00105 } 00106 code[9] = (code[9] >> 1) | (b ? 0x80 : 0); 00107 count ++; 00108 00109 if (code[8] == 0xfc && code[9] == 0xbf && count >= 80) { 00110 parse_code(); 00111 count = 0; 00112 } 00113 } 00114 00115 void LTC_SMPTE::parse_code () { 00116 frame = (code[1] & 0x03) * 10 + (code[0] & 0x0f); 00117 sec = (code[3] & 0x07) * 10 + (code[2] & 0x0f); 00118 min = (code[5] & 0x07) * 10 + (code[4] & 0x0f); 00119 hour = (code[7] & 0x03) * 10 + (code[6] & 0x0f); 00120 drop = code[1] & (1<<2) ? 1 : 0; 00121 received = 1; 00122 } 00123 00124 void LTC_SMPTE::read (int *hour, int *min, int *sec, int *frame, int *dir) { 00125 *hour = this->hour | (this->fps << 5); 00126 *min = this->min; 00127 *sec = this->sec; 00128 *frame = this->frame; 00129 if (dir) *dir = this->direction; 00130 received = 0; 00131 } 00132 00133 void LTC_SMPTE::write (int hour, int min, int sec, int frame, int dir) { 00134 if (type != LTC_OUTPUT) return; 00135 00136 US_TICKER_TIMER->TCR = 0; 00137 this->hour = hour; 00138 this->min = min; 00139 this->sec = sec; 00140 this->frame = frame; 00141 this->direction = dir; 00142 mode = 0; 00143 count = 0; 00144 00145 US_TICKER_TIMER->TCR = 0x2; // reset 00146 // set match value 00147 US_TICKER_TIMER->MR0 = 1; 00148 // enable match interrupt 00149 US_TICKER_TIMER->MCR |= 1; 00150 US_TICKER_TIMER->TCR = 1; // enable = 1, reset = 0 00151 00152 _timer.reset(); 00153 _timer.start(); 00154 __enable_irq(); 00155 } 00156 00157 void LTC_SMPTE::isr_ticker () { 00158 if (mode) { 00159 if (bit) { 00160 phase = !phase; 00161 _output->write(phase); 00162 } 00163 mode = 0; 00164 return; 00165 } 00166 00167 phase = !phase; 00168 _output->write(phase); 00169 mode = 1; 00170 00171 if (count >= 0 && count <= 3) { 00172 bit = (frame % 10) & (1 << count); 00173 } else 00174 if (count >= 8 && count <= 9) { 00175 bit = (frame / 10) & (1 << (count - 8)); 00176 } else 00177 if (count >= 16 && count <= 19) { 00178 bit = (sec % 10) & (1 << (count - 16)); 00179 } else 00180 if (count >= 24 && count <= 26) { 00181 bit = (sec / 10) & (1 << (count - 24)); 00182 } else 00183 if (count >= 32 && count <= 35) { 00184 bit = (min % 10) & (1 << (count - 32)); 00185 } else 00186 if (count >= 40 && count <= 42) { 00187 bit = (min / 10) & (1 << (count - 40)); 00188 } else 00189 if (count >= 48 && count <= 51) { 00190 bit = (hour % 10) & (1 << (count - 48)); 00191 } else 00192 if (count >= 56 && count <= 57) { 00193 bit = (hour / 10) & (1 << (count - 56)); 00194 } else 00195 if ((count >= 66 && count <= 77) || count == 79) { 00196 bit = 1; 00197 } else { 00198 bit = 0; 00199 } 00200 00201 count ++; 00202 if (count >= 80) { 00203 count = 0; 00204 frame ++; 00205 if (frame >= 30) { 00206 frame = 0; 00207 sec ++; 00208 if (sec >= 60) { 00209 sec = 0; 00210 min ++; 00211 if (min >= 60) { 00212 min = 0; 00213 hour ++; 00214 if (hour >= 24) { 00215 hour = 0; 00216 } 00217 } 00218 } 00219 } 00220 } 00221 } 00222 00223 int LTC_SMPTE::isReceived () { 00224 return received; 00225 }
Generated on Wed Jul 27 2022 05:49:11 by 1.7.2