Indrek Ardel / DMX-STM32 Featured

Fork of DMX by Suga koubou

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DMX.cpp Source File

DMX.cpp

Go to the documentation of this file.
00001 /*
00002  * DMX512 send/recv library
00003  * Copyright (c) 2013 Hiroshi Suga
00004  * Released under the MIT License: http://mbed.org/license/mit
00005  */
00006 
00007 /** @file
00008  * @brief DMX512 send/recv
00009  */
00010 
00011 #include "mbed.h"
00012 #include "DMX.h"
00013 
00014 DMX::DMX (PinName p_tx, PinName p_rx) : _dmx(p_tx, p_rx, 250000) {
00015     clear();
00016 //    mode_tx = DMX_MODE_BEGIN;
00017     mode_tx = DMX_MODE_STOP;
00018     mode_rx = DMX_MODE_BEGIN;
00019     is_received = 0;
00020     is_sent    = 0;
00021     time_break = DMX_TIME_BREAK;
00022     time_mab   = DMX_TIME_MAB;
00023     time_mbb   = DMX_TIME_MBB;
00024 
00025 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00026     if (p_rx == P0_3) {
00027       _uart = (LPC_UART_TypeDef*)LPC_UART0;
00028       NVIC_SetPriority(UART0_IRQn, 1);
00029     } else
00030     if (p_rx == p14) {
00031       _uart = (LPC_UART_TypeDef*)LPC_UART1;
00032       NVIC_SetPriority(UART1_IRQn, 1);
00033     } else
00034     if (p_rx == p27) {
00035       _uart = LPC_UART2;
00036       NVIC_SetPriority(UART2_IRQn, 1);
00037     } else
00038     if (p_rx == p10) {
00039       _uart = LPC_UART3;
00040       NVIC_SetPriority(UART3_IRQn, 1);
00041     }
00042 #elif defined(TARGET_LPC4088)
00043     if (p_rx == p10 || p_rx == P0_26 || p_rx == P4_29) {
00044       _uart = LPC_UART3;
00045       NVIC_SetPriority(UART3_IRQn, 1);
00046     } else
00047     if (p_rx == p31) {
00048       _uart = (LPC_UART_TypeDef*)LPC_UART4;
00049       NVIC_SetPriority(UART4_IRQn, 1);
00050     } else
00051     if (p_rx == P0_3) {
00052       _uart = LPC_UART0;
00053       NVIC_SetPriority(UART0_IRQn, 1);
00054     } else
00055     if (p_rx == P0_16 || p_rx == P2_1 || p_rx == P3_17) {
00056       _uart = (LPC_UART_TypeDef*)LPC_UART1;
00057       NVIC_SetPriority(UART1_IRQn, 1);
00058     } else
00059     if (p_rx == P0_11 || p_rx == P2_9 || p_rx == P4_23) {
00060       _uart = LPC_UART2;
00061       NVIC_SetPriority(UART2_IRQn, 1);
00062     }
00063 #elif defined(TARGET_LPC11UXX)
00064     if (p_rx == p10) {
00065       _uart = LPC_USART;
00066       NVIC_SetPriority(UART_IRQn, 1);
00067     }
00068 #elif defined(TARGET_LPC11XX)
00069     // LPC1114 support by Stanly Chen
00070     if (p_rx == P1_6) {
00071       _uart = (LPC_UART_TypeDef*)UART_0;
00072       NVIC_SetPriority(UART_IRQn, 1);
00073     }
00074 #elif defined(TARGET_NUCLEO_F303K8)
00075     if (p_rx == PA_10 || p_rx == PB_7) {
00076         _uart = (USART_TypeDef*) USART1;
00077         NVIC_SetPriority(USART1_IRQn, 1);
00078     } else
00079     if (p_rx == PA_3 || p_rx == PB_4) {
00080         _uart = (USART_TypeDef*) USART2;
00081         NVIC_SetPriority(USART2_IRQn, 1);
00082     }
00083 #endif
00084 
00085     _dmx.format(8, Serial::None, 2);
00086     _dmx.attach(callback(this, &DMX::int_rx), Serial::RxIrq);
00087 
00088 //    timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
00089 }
00090 
00091 void DMX::put (int addr, int data) {
00092     if (addr < 0 || addr >= DMX_SIZE) return;
00093     data_tx[addr] = data;
00094 }
00095 
00096 void DMX::put (unsigned char *buf, int addr, int len) {
00097     if (addr < 0 || addr >= DMX_SIZE) return;
00098     if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
00099     memcpy(&data_tx[addr], buf, len);
00100 }
00101 
00102 int DMX::get (int addr) {
00103     if (addr < 0 || addr >= DMX_SIZE) return -1;
00104     return data_rx[addr];
00105 }
00106 
00107 void DMX::get (unsigned char *buf, int addr, int len) {
00108     if (addr < 0 || addr >= DMX_SIZE) return;
00109     if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
00110     memcpy(buf, &data_rx[addr], len);
00111 }
00112 
00113 void DMX::int_timer () {
00114 
00115     switch (mode_tx) {
00116     case DMX_MODE_BEGIN:
00117         // Break Time
00118         timeout01.detach();
00119         #if defined(TARGET_STM)
00120             // TODO: I didn't need to send anything over DMX, so this is not implemented
00121             // If you wish to find out how to interface with USART on a low level, check
00122             // http://www.keil.com/dd/docs/datashts/st/stm32f3xx/dm00043574.pdf
00123         #else
00124             _uart->LCR |= (1 << 6);
00125         #endif
00126         mode_tx = DMX_MODE_BREAK;
00127         timeout01.attach_us(callback(this, &DMX::int_timer), time_break);
00128         break;
00129 
00130     case DMX_MODE_BREAK:
00131         // Mark After Break
00132         timeout01.detach();
00133         #if defined(TARGET_STM)
00134             // TODO see above
00135         #else
00136             _uart->LCR &= ~(1 << 6);
00137         #endif
00138         mode_tx = DMX_MODE_MAB;
00139         timeout01.attach_us(callback(this, &DMX::int_timer), time_mab);
00140         break;
00141 
00142     case DMX_MODE_MAB:
00143         // Start code
00144         timeout01.detach();
00145         addr_tx = 0;
00146         mode_tx = DMX_MODE_DATA;
00147         _dmx.attach(callback(this, &DMX::int_tx), Serial::TxIrq);
00148 #ifdef DMX_UART_DIRECT
00149         while(!(_uart->LSR & (1<<5)));
00150         _uart->THR = DMX_START_CODE;
00151 #else
00152         _dmx.putc(DMX_START_CODE);
00153 #endif
00154         break;
00155     }
00156 }
00157 
00158 void DMX::int_tx () {
00159     // Data
00160     if (mode_tx == DMX_MODE_DATA) {
00161         if (addr_tx < DMX_SIZE) {
00162 #ifdef DMX_UART_DIRECT
00163             _uart->THR = (uint8_t)data_tx[addr_tx];
00164 #else
00165             _dmx.putc(data_tx[addr_tx]);
00166 #endif
00167             addr_tx ++;
00168         } else {
00169             _dmx.attach(0, Serial::TxIrq);
00170             mode_tx = DMX_MODE_BEGIN;
00171             is_sent = 1;
00172             timeout01.attach_us(callback(this, &DMX::int_timer), time_mbb);
00173         }
00174     }
00175 }
00176 
00177 void DMX::int_rx () {
00178     int flg, dat;
00179 
00180     #ifdef TARGET_STM
00181         dat = _dmx.getc();
00182         flg = (_uart->ISR & (USART_FLAG_FE | USART_ISR_IDLE)) == (USART_FLAG_FE | USART_ISR_IDLE);
00183         if (flg) {
00184             _uart->ICR = USART_ICR_FECF;
00185         }
00186     #else
00187         flg = _uart->LSR & ((1 << 7)|(1 << 3)|(1 << 4));
00188         #ifdef DMX_UART_DIRECT
00189             dat = _uart->RBR;
00190         #else
00191             dat = _dmx.getc();
00192         #endif
00193     #endif
00194 
00195     if (flg) {
00196         // Break Time
00197         if (addr_rx >= 24 && mode_rx == DMX_MODE_DATA) {
00198             on_received();
00199         }
00200         mode_rx = DMX_MODE_BREAK;
00201         return;
00202     }
00203 
00204     if (mode_rx == DMX_MODE_BREAK) {
00205 
00206         // Start Code
00207         if (dat == DMX_START_CODE) {
00208             addr_rx = 0;
00209             mode_rx = DMX_MODE_DATA;
00210         } else {
00211             mode_rx = DMX_MODE_ERROR;
00212         }
00213 
00214     } else
00215     if (mode_rx == DMX_MODE_DATA) {
00216 
00217         // Data
00218         data_rx_working[addr_rx] = dat;
00219         addr_rx ++;
00220 
00221         if (addr_rx >= DMX_SIZE) {
00222             on_received();
00223             mode_rx = DMX_MODE_BEGIN;
00224         }
00225     }
00226 }
00227 
00228 void DMX::start () {
00229     if (mode_tx == DMX_MODE_STOP) {
00230         mode_tx = DMX_MODE_BEGIN;
00231         is_sent = 0;
00232         timeout01.attach_us(callback(this, &DMX::int_timer), time_mbb);
00233     }
00234 }
00235 
00236 void DMX::stop () {
00237     _dmx.attach(0, Serial::TxIrq);
00238     timeout01.detach();
00239     mode_tx = DMX_MODE_STOP;
00240 }
00241 
00242 void DMX::clear () {
00243     memset(data_rx, 0, sizeof(data_rx));
00244     memset(data_tx, 0, sizeof(data_rx));
00245     memset(data_rx_working, 0, sizeof(data_rx_working));
00246 }
00247 
00248 int DMX::isReceived (){
00249     int r = is_received;
00250     is_received = 0;
00251     return r;
00252 }
00253 
00254 int DMX::isSent () {
00255     int r = is_sent;
00256     is_sent = 0;
00257     return r;
00258 }
00259 
00260 unsigned char *DMX::getRxBuffer () {
00261     return data_rx;
00262 }
00263 
00264 unsigned char *DMX::getTxBuffer () {
00265     return data_tx;
00266 }
00267 
00268 int DMX::setTimingParameters (int breaktime, int mab, int mbb) {
00269     if (breaktime < 88 || breaktime > 1000000) return -1;
00270     if (mab < 8 || mab > 1000000) return -1;
00271     if (mbb < 0 || mbb > 1000000) return -1;
00272 
00273     time_break = breaktime;
00274     time_mab   = mab;
00275     time_mbb   = mbb;
00276     return 0;
00277 }
00278 
00279 void DMX::attach(void (*function)(void)) {
00280     on_rx.attach(function);
00281 }
00282 
00283 void DMX::on_received() {
00284     memcpy(data_rx, data_rx_working, sizeof(data_rx_working));
00285     is_received = 1;
00286     on_rx.call();
00287 }