DMX512 send/recv library with STM32 slave support originally from http://mbed.org/users/okini3939/notebook/dmx512

Fork of DMX by Suga koubou

Committer:
Ingram
Date:
Tue May 31 11:02:49 2016 +0000
Revision:
20:908740273e88
Parent:
19:6534f3ffdfec
Child:
21:36276a92303f
Add function pointer for "on dmx frame received" and use memset in clear()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:cbff6bf41542 1 /*
okini3939 0:cbff6bf41542 2 * DMX512 send/recv library
okini3939 6:9e7b4eeac6ec 3 * Copyright (c) 2013 Hiroshi Suga
okini3939 0:cbff6bf41542 4 * Released under the MIT License: http://mbed.org/license/mit
okini3939 0:cbff6bf41542 5 */
okini3939 0:cbff6bf41542 6
okini3939 7:16d6874076dd 7 /** @file
okini3939 0:cbff6bf41542 8 * @brief DMX512 send/recv
okini3939 0:cbff6bf41542 9 */
okini3939 0:cbff6bf41542 10
okini3939 0:cbff6bf41542 11 #include "mbed.h"
okini3939 0:cbff6bf41542 12 #include "DMX.h"
okini3939 0:cbff6bf41542 13
okini3939 5:72039cd4c874 14 DMX::DMX (PinName p_tx, PinName p_rx) : _dmx(p_tx, p_rx) {
okini3939 0:cbff6bf41542 15
okini3939 12:1f176eee2d28 16 clear();
okini3939 4:dd0544c80096 17 // mode_tx = DMX_MODE_BEGIN;
okini3939 4:dd0544c80096 18 mode_tx = DMX_MODE_STOP;
okini3939 0:cbff6bf41542 19 mode_rx = DMX_MODE_BEGIN;
okini3939 18:69d65ca92bcc 20 is_received = 0;
okini3939 18:69d65ca92bcc 21 is_sent = 0;
okini3939 18:69d65ca92bcc 22 time_break = DMX_TIME_BREAK;
okini3939 18:69d65ca92bcc 23 time_mab = DMX_TIME_MAB;
okini3939 18:69d65ca92bcc 24 time_mbb = DMX_TIME_MBB;
okini3939 0:cbff6bf41542 25
okini3939 5:72039cd4c874 26 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
okini3939 11:cb132e066057 27 if (p_rx == P0_3) {
okini3939 11:cb132e066057 28 _uart = (LPC_UART_TypeDef*)LPC_UART0;
okini3939 11:cb132e066057 29 NVIC_SetPriority(UART0_IRQn, 1);
okini3939 0:cbff6bf41542 30 } else
okini3939 0:cbff6bf41542 31 if (p_rx == p14) {
okini3939 8:d4a45bba41d2 32 _uart = (LPC_UART_TypeDef*)LPC_UART1;
okini3939 0:cbff6bf41542 33 NVIC_SetPriority(UART1_IRQn, 1);
okini3939 0:cbff6bf41542 34 } else
okini3939 0:cbff6bf41542 35 if (p_rx == p27) {
okini3939 8:d4a45bba41d2 36 _uart = LPC_UART2;
okini3939 0:cbff6bf41542 37 NVIC_SetPriority(UART2_IRQn, 1);
okini3939 11:cb132e066057 38 } else
okini3939 11:cb132e066057 39 if (p_rx == p10) {
okini3939 11:cb132e066057 40 _uart = LPC_UART3;
okini3939 11:cb132e066057 41 NVIC_SetPriority(UART3_IRQn, 1);
okini3939 0:cbff6bf41542 42 }
okini3939 13:9841af9ac344 43 #elif defined(TARGET_LPC4088)
okini3939 16:4eeb749806e5 44 if (p_rx == p10 || p_rx == P0_26 || p_rx == P4_29) {
okini3939 13:9841af9ac344 45 _uart = LPC_UART3;
okini3939 13:9841af9ac344 46 NVIC_SetPriority(UART3_IRQn, 1);
okini3939 13:9841af9ac344 47 } else
okini3939 13:9841af9ac344 48 if (p_rx == p31) {
okini3939 13:9841af9ac344 49 _uart = (LPC_UART_TypeDef*)LPC_UART4;
okini3939 13:9841af9ac344 50 NVIC_SetPriority(UART4_IRQn, 1);
okini3939 16:4eeb749806e5 51 } else
okini3939 16:4eeb749806e5 52 if (p_rx == P0_3) {
okini3939 16:4eeb749806e5 53 _uart = LPC_UART0;
okini3939 16:4eeb749806e5 54 NVIC_SetPriority(UART0_IRQn, 1);
okini3939 16:4eeb749806e5 55 } else
okini3939 16:4eeb749806e5 56 if (p_rx == P0_16 || p_rx == P2_1 || p_rx == P3_17) {
okini3939 16:4eeb749806e5 57 _uart = (LPC_UART_TypeDef*)LPC_UART1;
okini3939 16:4eeb749806e5 58 NVIC_SetPriority(UART1_IRQn, 1);
okini3939 16:4eeb749806e5 59 } else
okini3939 16:4eeb749806e5 60 if (p_rx == P0_11 || p_rx == P2_9 || p_rx == P4_23) {
okini3939 16:4eeb749806e5 61 _uart = LPC_UART2;
okini3939 16:4eeb749806e5 62 NVIC_SetPriority(UART2_IRQn, 1);
okini3939 13:9841af9ac344 63 }
okini3939 15:4ea4a31c7609 64 #elif defined(TARGET_LPC11UXX)
okini3939 5:72039cd4c874 65 if (p_rx == p10) {
okini3939 8:d4a45bba41d2 66 _uart = LPC_USART;
okini3939 5:72039cd4c874 67 NVIC_SetPriority(UART_IRQn, 1);
okini3939 5:72039cd4c874 68 }
stanly88 10:b748aab8404c 69 #elif defined(TARGET_LPC11XX)
okini3939 11:cb132e066057 70 // LPC1114 support by Stanly Chen
stanly88 10:b748aab8404c 71 if (p_rx == P1_6) {
okini3939 13:9841af9ac344 72 _uart = (LPC_UART_TypeDef*)UART_0;
stanly88 10:b748aab8404c 73 NVIC_SetPriority(UART_IRQn, 1);
stanly88 10:b748aab8404c 74 }
Ingram 19:6534f3ffdfec 75 #elif defined(TARGET_NUCLEO_F303K8)
Ingram 19:6534f3ffdfec 76 if (p_rx == PA_10 || p_rx == PB_7) {
Ingram 19:6534f3ffdfec 77 _uart = (USART_TypeDef*) USART1;
Ingram 19:6534f3ffdfec 78 NVIC_SetPriority(USART1_IRQn, 1);
Ingram 19:6534f3ffdfec 79 } else
Ingram 19:6534f3ffdfec 80 if (p_rx == PA_3 || p_rx == PB_4) {
Ingram 19:6534f3ffdfec 81 _uart = (USART_TypeDef*) USART2;
Ingram 19:6534f3ffdfec 82 NVIC_SetPriority(USART2_IRQn, 1);
Ingram 19:6534f3ffdfec 83 }
okini3939 5:72039cd4c874 84 #endif
okini3939 0:cbff6bf41542 85
okini3939 5:72039cd4c874 86 _dmx.baud(250000);
okini3939 5:72039cd4c874 87 _dmx.format(8, Serial::None, 2);
okini3939 5:72039cd4c874 88 _dmx.attach(this, &DMX::int_rx, Serial::RxIrq);
okini3939 0:cbff6bf41542 89
okini3939 4:dd0544c80096 90 // timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
okini3939 0:cbff6bf41542 91 }
okini3939 0:cbff6bf41542 92
okini3939 6:9e7b4eeac6ec 93 void DMX::put (int addr, int data) {
okini3939 6:9e7b4eeac6ec 94 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 95 data_tx[addr] = data;
okini3939 0:cbff6bf41542 96 }
okini3939 0:cbff6bf41542 97
okini3939 6:9e7b4eeac6ec 98 void DMX::put (unsigned char *buf, int addr, int len) {
okini3939 6:9e7b4eeac6ec 99 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 100 if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
okini3939 6:9e7b4eeac6ec 101 memcpy(&data_tx[addr], buf, len);
okini3939 6:9e7b4eeac6ec 102 }
okini3939 6:9e7b4eeac6ec 103
okini3939 6:9e7b4eeac6ec 104 int DMX::get (int addr) {
okini3939 6:9e7b4eeac6ec 105 if (addr < 0 || addr >= DMX_SIZE) return -1;
okini3939 6:9e7b4eeac6ec 106 return data_rx[addr];
okini3939 6:9e7b4eeac6ec 107 }
okini3939 6:9e7b4eeac6ec 108
okini3939 6:9e7b4eeac6ec 109 void DMX::get (unsigned char *buf, int addr, int len) {
okini3939 6:9e7b4eeac6ec 110 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 111 if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
okini3939 6:9e7b4eeac6ec 112 memcpy(buf, &data_rx[addr], len);
okini3939 0:cbff6bf41542 113 }
okini3939 0:cbff6bf41542 114
okini3939 0:cbff6bf41542 115 void DMX::int_timer () {
okini3939 0:cbff6bf41542 116
okini3939 0:cbff6bf41542 117 switch (mode_tx) {
okini3939 0:cbff6bf41542 118 case DMX_MODE_BEGIN:
okini3939 0:cbff6bf41542 119 // Break Time
okini3939 0:cbff6bf41542 120 timeout01.detach();
Ingram 19:6534f3ffdfec 121 #if defined(TARGET_STM)
Ingram 19:6534f3ffdfec 122 // TODO: I didn't need to send anything over DMX, so this is not implemented
Ingram 19:6534f3ffdfec 123 // If you wish to find out how to interface with USART on a low level, check
Ingram 19:6534f3ffdfec 124 // http://www.keil.com/dd/docs/datashts/st/stm32f3xx/dm00043574.pdf
Ingram 19:6534f3ffdfec 125 #else
Ingram 19:6534f3ffdfec 126 _uart->LCR |= (1 << 6);
Ingram 19:6534f3ffdfec 127 #endif
okini3939 0:cbff6bf41542 128 mode_tx = DMX_MODE_BREAK;
okini3939 18:69d65ca92bcc 129 timeout01.attach_us(this, &DMX::int_timer, time_break);
okini3939 0:cbff6bf41542 130 break;
okini3939 0:cbff6bf41542 131
okini3939 0:cbff6bf41542 132 case DMX_MODE_BREAK:
okini3939 0:cbff6bf41542 133 // Mark After Break
okini3939 0:cbff6bf41542 134 timeout01.detach();
Ingram 19:6534f3ffdfec 135 #if defined(TARGET_STM)
Ingram 19:6534f3ffdfec 136 // TODO see above
Ingram 19:6534f3ffdfec 137 #else
Ingram 19:6534f3ffdfec 138 _uart->LCR &= ~(1 << 6);
Ingram 19:6534f3ffdfec 139 #endif
okini3939 0:cbff6bf41542 140 mode_tx = DMX_MODE_MAB;
okini3939 18:69d65ca92bcc 141 timeout01.attach_us(this, &DMX::int_timer, time_mab);
okini3939 0:cbff6bf41542 142 break;
okini3939 0:cbff6bf41542 143
okini3939 0:cbff6bf41542 144 case DMX_MODE_MAB:
okini3939 0:cbff6bf41542 145 // Start code
okini3939 0:cbff6bf41542 146 timeout01.detach();
okini3939 0:cbff6bf41542 147 addr_tx = 0;
okini3939 0:cbff6bf41542 148 mode_tx = DMX_MODE_DATA;
okini3939 5:72039cd4c874 149 _dmx.attach(this, &DMX::int_tx, Serial::TxIrq);
okini3939 2:d7677060f8eb 150 #ifdef DMX_UART_DIRECT
okini3939 9:e687f321c428 151 while(!(_uart->LSR & (1<<5)));
okini3939 9:e687f321c428 152 _uart->THR = DMX_START_CODE;
okini3939 2:d7677060f8eb 153 #else
okini3939 9:e687f321c428 154 _dmx.putc(DMX_START_CODE);
okini3939 2:d7677060f8eb 155 #endif
okini3939 0:cbff6bf41542 156 break;
okini3939 0:cbff6bf41542 157 }
okini3939 0:cbff6bf41542 158 }
okini3939 0:cbff6bf41542 159
okini3939 0:cbff6bf41542 160 void DMX::int_tx () {
okini3939 0:cbff6bf41542 161 // Data
okini3939 0:cbff6bf41542 162 if (mode_tx == DMX_MODE_DATA) {
okini3939 0:cbff6bf41542 163 if (addr_tx < DMX_SIZE) {
okini3939 1:f0d988e15810 164 #ifdef DMX_UART_DIRECT
okini3939 8:d4a45bba41d2 165 _uart->THR = (uint8_t)data_tx[addr_tx];
okini3939 0:cbff6bf41542 166 #else
okini3939 5:72039cd4c874 167 _dmx.putc(data_tx[addr_tx]);
okini3939 0:cbff6bf41542 168 #endif
okini3939 0:cbff6bf41542 169 addr_tx ++;
okini3939 0:cbff6bf41542 170 } else {
okini3939 5:72039cd4c874 171 _dmx.attach(0, Serial::TxIrq);
okini3939 0:cbff6bf41542 172 mode_tx = DMX_MODE_BEGIN;
okini3939 0:cbff6bf41542 173 is_sent = 1;
okini3939 18:69d65ca92bcc 174 timeout01.attach_us(this, &DMX::int_timer, time_mbb);
okini3939 0:cbff6bf41542 175 }
okini3939 0:cbff6bf41542 176 }
okini3939 0:cbff6bf41542 177 }
okini3939 0:cbff6bf41542 178
okini3939 0:cbff6bf41542 179 void DMX::int_rx () {
okini3939 0:cbff6bf41542 180 int flg, dat;
okini3939 0:cbff6bf41542 181
Ingram 19:6534f3ffdfec 182 #ifdef TARGET_STM
Ingram 19:6534f3ffdfec 183 dat = _dmx.getc();
Ingram 19:6534f3ffdfec 184 flg = (_uart->ISR & (USART_FLAG_FE | USART_ISR_IDLE)) == (USART_FLAG_FE | USART_ISR_IDLE);
Ingram 19:6534f3ffdfec 185 if (flg) {
Ingram 19:6534f3ffdfec 186 _uart->ICR = USART_ICR_FECF;
Ingram 19:6534f3ffdfec 187 }
Ingram 19:6534f3ffdfec 188 #else
Ingram 19:6534f3ffdfec 189 flg = _uart->LSR & ((1 << 7)|(1 << 3)|(1 << 4));
Ingram 19:6534f3ffdfec 190 #ifdef DMX_UART_DIRECT
Ingram 19:6534f3ffdfec 191 dat = _uart->RBR;
Ingram 19:6534f3ffdfec 192 #else
Ingram 19:6534f3ffdfec 193 dat = _dmx.getc();
Ingram 19:6534f3ffdfec 194 #endif
Ingram 19:6534f3ffdfec 195 #endif
okini3939 0:cbff6bf41542 196
Ingram 19:6534f3ffdfec 197 if (flg) {
okini3939 0:cbff6bf41542 198 // Break Time
okini3939 15:4ea4a31c7609 199 if (addr_rx >= 24 && mode_rx == DMX_MODE_DATA) {
Ingram 20:908740273e88 200 on_received();
okini3939 0:cbff6bf41542 201 }
okini3939 0:cbff6bf41542 202 mode_rx = DMX_MODE_BREAK;
okini3939 0:cbff6bf41542 203 return;
okini3939 0:cbff6bf41542 204 }
okini3939 0:cbff6bf41542 205
okini3939 0:cbff6bf41542 206 if (mode_rx == DMX_MODE_BREAK) {
okini3939 0:cbff6bf41542 207
okini3939 0:cbff6bf41542 208 // Start Code
okini3939 9:e687f321c428 209 if (dat == DMX_START_CODE) {
okini3939 0:cbff6bf41542 210 addr_rx = 0;
okini3939 0:cbff6bf41542 211 mode_rx = DMX_MODE_DATA;
okini3939 0:cbff6bf41542 212 } else {
okini3939 0:cbff6bf41542 213 mode_rx = DMX_MODE_ERROR;
okini3939 0:cbff6bf41542 214 }
okini3939 0:cbff6bf41542 215
okini3939 0:cbff6bf41542 216 } else
okini3939 0:cbff6bf41542 217 if (mode_rx == DMX_MODE_DATA) {
okini3939 0:cbff6bf41542 218
okini3939 0:cbff6bf41542 219 // Data
Ingram 20:908740273e88 220 data_rx_working[addr_rx] = dat;
okini3939 0:cbff6bf41542 221 addr_rx ++;
okini3939 0:cbff6bf41542 222
okini3939 0:cbff6bf41542 223 if (addr_rx >= DMX_SIZE) {
Ingram 20:908740273e88 224 on_received();
okini3939 0:cbff6bf41542 225 mode_rx = DMX_MODE_BEGIN;
okini3939 0:cbff6bf41542 226 }
okini3939 0:cbff6bf41542 227 }
okini3939 0:cbff6bf41542 228 }
okini3939 0:cbff6bf41542 229
okini3939 4:dd0544c80096 230 void DMX::start () {
okini3939 4:dd0544c80096 231 if (mode_tx == DMX_MODE_STOP) {
okini3939 4:dd0544c80096 232 mode_tx = DMX_MODE_BEGIN;
okini3939 4:dd0544c80096 233 is_sent = 0;
okini3939 18:69d65ca92bcc 234 timeout01.attach_us(this, &DMX::int_timer, time_mbb);
okini3939 4:dd0544c80096 235 }
okini3939 4:dd0544c80096 236 }
okini3939 4:dd0544c80096 237
okini3939 4:dd0544c80096 238 void DMX::stop () {
okini3939 5:72039cd4c874 239 _dmx.attach(0, Serial::TxIrq);
okini3939 3:2eb66b4d99bd 240 timeout01.detach();
okini3939 4:dd0544c80096 241 mode_tx = DMX_MODE_STOP;
okini3939 3:2eb66b4d99bd 242 }
okini3939 12:1f176eee2d28 243
okini3939 12:1f176eee2d28 244 void DMX::clear () {
Ingram 20:908740273e88 245 memset(data_rx, 0, sizeof(data_rx));
Ingram 20:908740273e88 246 memset(data_tx, 0, sizeof(data_rx));
Ingram 20:908740273e88 247 memset(data_rx_working, 0, sizeof(data_rx_working));
okini3939 12:1f176eee2d28 248 }
okini3939 17:c9198630ba05 249
okini3939 18:69d65ca92bcc 250 int DMX::isReceived (){
okini3939 18:69d65ca92bcc 251 int r = is_received;
okini3939 18:69d65ca92bcc 252 is_received = 0;
okini3939 17:c9198630ba05 253 return r;
okini3939 17:c9198630ba05 254 }
okini3939 17:c9198630ba05 255
okini3939 17:c9198630ba05 256 int DMX::isSent () {
okini3939 17:c9198630ba05 257 int r = is_sent;
okini3939 17:c9198630ba05 258 is_sent = 0;
okini3939 17:c9198630ba05 259 return r;
okini3939 17:c9198630ba05 260 }
okini3939 17:c9198630ba05 261
okini3939 17:c9198630ba05 262 unsigned char *DMX::getRxBuffer () {
okini3939 17:c9198630ba05 263 return data_rx;
okini3939 17:c9198630ba05 264 }
okini3939 17:c9198630ba05 265
okini3939 17:c9198630ba05 266 unsigned char *DMX::getTxBuffer () {
okini3939 17:c9198630ba05 267 return data_tx;
okini3939 17:c9198630ba05 268 }
okini3939 18:69d65ca92bcc 269
okini3939 18:69d65ca92bcc 270 int DMX::setTimingParameters (int breaktime, int mab, int mbb) {
okini3939 18:69d65ca92bcc 271 if (breaktime < 88 || breaktime > 1000000) return -1;
okini3939 18:69d65ca92bcc 272 if (mab < 8 || mab > 1000000) return -1;
okini3939 18:69d65ca92bcc 273 if (mbb < 0 || mbb > 1000000) return -1;
okini3939 18:69d65ca92bcc 274
okini3939 18:69d65ca92bcc 275 time_break = breaktime;
okini3939 18:69d65ca92bcc 276 time_mab = mab;
okini3939 18:69d65ca92bcc 277 time_mbb = mbb;
okini3939 18:69d65ca92bcc 278 return 0;
okini3939 18:69d65ca92bcc 279 }
Ingram 20:908740273e88 280
Ingram 20:908740273e88 281 void DMX::attach(void (*function)(void)) {
Ingram 20:908740273e88 282 on_rx.attach(function);
Ingram 20:908740273e88 283 }
Ingram 20:908740273e88 284
Ingram 20:908740273e88 285 void DMX::on_received() {
Ingram 20:908740273e88 286 memcpy(data_rx, data_rx_working, sizeof(data_rx_working));
Ingram 20:908740273e88 287 is_received = 1;
Ingram 20:908740273e88 288 on_rx.call();
Ingram 20:908740273e88 289 }