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:
Wed Apr 27 14:26:20 2016 +0000
Revision:
19:6534f3ffdfec
Parent:
18:69d65ca92bcc
Child:
20:908740273e88
Add STM32 DMX Slave support

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