An initial port to the FRDM-K46Z based on the the following: https://developer.mbed.org/users/okini3939/notebook/dmx512/

Dependents:   FRDM-Dowser

Fork of DMX by Suga koubou

Need to update the UART references to the K46Z. The KE02 Sub-Family Reference Manual provides us with the required information.

The modifications are wrapped with the target for the K46: For example, defined(TARGET_KL46Z)

Committer:
rosienej
Date:
Thu Mar 26 17:09:33 2015 +0000
Revision:
19:8a86e35e54a9
Parent:
18:6303931e4102
Child:
20:b1942f266f49
Updated comments and added a decode helper routine.

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 0:cbff6bf41542 20 is_recived = 0;
okini3939 0:cbff6bf41542 21 is_sent = 0;
okini3939 0:cbff6bf41542 22
okini3939 5:72039cd4c874 23 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
okini3939 11:cb132e066057 24 if (p_rx == P0_3) {
okini3939 11:cb132e066057 25 _uart = (LPC_UART_TypeDef*)LPC_UART0;
okini3939 11:cb132e066057 26 NVIC_SetPriority(UART0_IRQn, 1);
okini3939 0:cbff6bf41542 27 } else
okini3939 0:cbff6bf41542 28 if (p_rx == p14) {
okini3939 8:d4a45bba41d2 29 _uart = (LPC_UART_TypeDef*)LPC_UART1;
okini3939 0:cbff6bf41542 30 NVIC_SetPriority(UART1_IRQn, 1);
okini3939 0:cbff6bf41542 31 } else
okini3939 0:cbff6bf41542 32 if (p_rx == p27) {
okini3939 8:d4a45bba41d2 33 _uart = LPC_UART2;
okini3939 0:cbff6bf41542 34 NVIC_SetPriority(UART2_IRQn, 1);
okini3939 11:cb132e066057 35 } else
okini3939 11:cb132e066057 36 if (p_rx == p10) {
okini3939 11:cb132e066057 37 _uart = LPC_UART3;
okini3939 11:cb132e066057 38 NVIC_SetPriority(UART3_IRQn, 1);
okini3939 0:cbff6bf41542 39 }
rosienej 16:84a017ef96f8 40 #elif defined(TARGET_KL46Z)
rosienej 18:6303931e4102 41 /**
rosienej 18:6303931e4102 42 Need to associate the _uart private variable with the user selected pin.
rosienej 18:6303931e4102 43 Hook the interrupt pin.
rosienej 18:6303931e4102 44 */
rosienej 16:84a017ef96f8 45 if ((p_rx == PTE21) || (p_rx == PTA1)){
rosienej 16:84a017ef96f8 46 _uart = (UARTLP_Type *)UART0;
rosienej 16:84a017ef96f8 47 NVIC_SetPriority(UART0_IRQn, 1);
rosienej 16:84a017ef96f8 48 } else
rosienej 16:84a017ef96f8 49 if (p_rx == PTE1) {
rosienej 16:84a017ef96f8 50 _uart = (UARTLP_Type *)UART1;
rosienej 16:84a017ef96f8 51 NVIC_SetPriority(UART1_IRQn, 1);
rosienej 16:84a017ef96f8 52 } else
rosienej 16:84a017ef96f8 53 if ((p_rx == PTE23) || (p_rx == PTE17)) {
rosienej 16:84a017ef96f8 54 _uart = (UARTLP_Type *)UART2;
rosienej 16:84a017ef96f8 55 NVIC_SetPriority(UART2_IRQn, 1);
rosienej 17:12dd79109ce3 56 }
rosienej 16:84a017ef96f8 57
okini3939 13:9841af9ac344 58 #elif defined(TARGET_LPC4088)
okini3939 13:9841af9ac344 59 if (p_rx == p10) {
okini3939 13:9841af9ac344 60 _uart = LPC_UART3;
okini3939 13:9841af9ac344 61 NVIC_SetPriority(UART3_IRQn, 1);
okini3939 13:9841af9ac344 62 } else
okini3939 13:9841af9ac344 63 if (p_rx == p31) {
okini3939 13:9841af9ac344 64 _uart = (LPC_UART_TypeDef*)LPC_UART4;
okini3939 13:9841af9ac344 65 NVIC_SetPriority(UART4_IRQn, 1);
okini3939 13:9841af9ac344 66 }
okini3939 15:4ea4a31c7609 67 #elif defined(TARGET_LPC11UXX)
okini3939 5:72039cd4c874 68 if (p_rx == p10) {
okini3939 8:d4a45bba41d2 69 _uart = LPC_USART;
okini3939 5:72039cd4c874 70 NVIC_SetPriority(UART_IRQn, 1);
okini3939 5:72039cd4c874 71 }
stanly88 10:b748aab8404c 72 #elif defined(TARGET_LPC11XX)
okini3939 11:cb132e066057 73 // LPC1114 support by Stanly Chen
stanly88 10:b748aab8404c 74 if (p_rx == P1_6) {
okini3939 13:9841af9ac344 75 _uart = (LPC_UART_TypeDef*)UART_0;
stanly88 10:b748aab8404c 76 NVIC_SetPriority(UART_IRQn, 1);
stanly88 10:b748aab8404c 77 }
okini3939 5:72039cd4c874 78 #endif
okini3939 0:cbff6bf41542 79
okini3939 5:72039cd4c874 80 _dmx.baud(250000);
okini3939 5:72039cd4c874 81 _dmx.format(8, Serial::None, 2);
okini3939 5:72039cd4c874 82 _dmx.attach(this, &DMX::int_rx, Serial::RxIrq);
okini3939 0:cbff6bf41542 83
okini3939 4:dd0544c80096 84 // timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
okini3939 0:cbff6bf41542 85 }
okini3939 0:cbff6bf41542 86
okini3939 6:9e7b4eeac6ec 87 void DMX::put (int addr, int data) {
okini3939 6:9e7b4eeac6ec 88 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 89 data_tx[addr] = data;
okini3939 0:cbff6bf41542 90 }
okini3939 0:cbff6bf41542 91
okini3939 6:9e7b4eeac6ec 92 void DMX::put (unsigned char *buf, int addr, int len) {
okini3939 6:9e7b4eeac6ec 93 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 94 if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
okini3939 6:9e7b4eeac6ec 95 memcpy(&data_tx[addr], buf, len);
okini3939 6:9e7b4eeac6ec 96 }
okini3939 6:9e7b4eeac6ec 97
okini3939 6:9e7b4eeac6ec 98 int DMX::get (int addr) {
okini3939 6:9e7b4eeac6ec 99 if (addr < 0 || addr >= DMX_SIZE) return -1;
okini3939 6:9e7b4eeac6ec 100 return data_rx[addr];
okini3939 6:9e7b4eeac6ec 101 }
okini3939 6:9e7b4eeac6ec 102
okini3939 6:9e7b4eeac6ec 103 void DMX::get (unsigned char *buf, int addr, int len) {
okini3939 6:9e7b4eeac6ec 104 if (addr < 0 || addr >= DMX_SIZE) return;
okini3939 6:9e7b4eeac6ec 105 if (len > DMX_SIZE - addr) len = DMX_SIZE - addr;
okini3939 6:9e7b4eeac6ec 106 memcpy(buf, &data_rx[addr], len);
okini3939 0:cbff6bf41542 107 }
okini3939 0:cbff6bf41542 108
okini3939 0:cbff6bf41542 109 void DMX::int_timer () {
okini3939 0:cbff6bf41542 110
okini3939 0:cbff6bf41542 111 switch (mode_tx) {
okini3939 0:cbff6bf41542 112 case DMX_MODE_BEGIN:
okini3939 0:cbff6bf41542 113 // Break Time
okini3939 0:cbff6bf41542 114 timeout01.detach();
rosienej 16:84a017ef96f8 115 #if defined(TARGET_KL46Z)
rosienej 19:8a86e35e54a9 116 /// Chapter 31.2 of the Freescale KE02 Sub-Famely Reference
rosienej 18:6303931e4102 117 /// UARTx_C2 page 553 enable the transmitter and reciever
rosienej 18:6303931e4102 118 /// Sending a break we write a one, then write a zero..... This sets send break bit
rosienej 16:84a017ef96f8 119 _uart->C2 |= UART_C2_SBK_MASK | UART_C2_TE_MASK | UART_C2_RE_MASK;
rosienej 16:84a017ef96f8 120 #else
rosienej 18:6303931e4102 121 /// Bit 6 in the LCR enables the break signal.....
rosienej 16:84a017ef96f8 122 _uart->LCR |= (1 << 6);
rosienej 16:84a017ef96f8 123 #endif
okini3939 0:cbff6bf41542 124 mode_tx = DMX_MODE_BREAK;
okini3939 0:cbff6bf41542 125 timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BREAK);
okini3939 0:cbff6bf41542 126 break;
okini3939 0:cbff6bf41542 127
okini3939 0:cbff6bf41542 128 case DMX_MODE_BREAK:
okini3939 0:cbff6bf41542 129 // Mark After Break
okini3939 0:cbff6bf41542 130 timeout01.detach();
rosienej 16:84a017ef96f8 131 #if defined(TARGET_KL46Z)
rosienej 18:6303931e4102 132 /// This sets the break charcter to zero to send the break.
rosienej 16:84a017ef96f8 133 _uart->C2 &= ~UART_C2_SBK_MASK;
rosienej 16:84a017ef96f8 134 #else
okini3939 8:d4a45bba41d2 135 _uart->LCR &= ~(1 << 6);
rosienej 16:84a017ef96f8 136 #endif
okini3939 0:cbff6bf41542 137 mode_tx = DMX_MODE_MAB;
okini3939 0:cbff6bf41542 138 timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_MAB);
okini3939 0:cbff6bf41542 139 break;
okini3939 0:cbff6bf41542 140
okini3939 0:cbff6bf41542 141 case DMX_MODE_MAB:
okini3939 0:cbff6bf41542 142 // Start code
okini3939 0:cbff6bf41542 143 timeout01.detach();
okini3939 0:cbff6bf41542 144 addr_tx = 0;
okini3939 0:cbff6bf41542 145 mode_tx = DMX_MODE_DATA;
okini3939 5:72039cd4c874 146 _dmx.attach(this, &DMX::int_tx, Serial::TxIrq);
okini3939 2:d7677060f8eb 147 #ifdef DMX_UART_DIRECT
rosienej 16:84a017ef96f8 148
rosienej 16:84a017ef96f8 149
rosienej 16:84a017ef96f8 150 #if defined(TARGET_KL46Z)
rosienej 18:6303931e4102 151 /// Check the TDRE (Transmit Data Register Empty) flag... page 555
rosienej 18:6303931e4102 152 /// The data is placed in D on the Freescale
rosienej 16:84a017ef96f8 153 while(!(_uart->S1 & UART_S1_TDRE_MASK));
rosienej 16:84a017ef96f8 154 _uart->D = DMX_START_CODE; // Freescale
rosienej 16:84a017ef96f8 155 #else
rosienej 18:6303931e4102 156 /// Bit 5 of the LSR indicates the THR (Transmit Holding Register) is empty
okini3939 9:e687f321c428 157 while(!(_uart->LSR & (1<<5)));
okini3939 9:e687f321c428 158 _uart->THR = DMX_START_CODE;
rosienej 16:84a017ef96f8 159 #endif
okini3939 2:d7677060f8eb 160 #else
okini3939 9:e687f321c428 161 _dmx.putc(DMX_START_CODE);
okini3939 2:d7677060f8eb 162 #endif
okini3939 0:cbff6bf41542 163 break;
okini3939 0:cbff6bf41542 164 }
okini3939 0:cbff6bf41542 165 }
okini3939 0:cbff6bf41542 166
okini3939 0:cbff6bf41542 167 void DMX::int_tx () {
okini3939 0:cbff6bf41542 168 // Data
okini3939 0:cbff6bf41542 169 if (mode_tx == DMX_MODE_DATA) {
okini3939 0:cbff6bf41542 170 if (addr_tx < DMX_SIZE) {
okini3939 1:f0d988e15810 171 #ifdef DMX_UART_DIRECT
rosienej 16:84a017ef96f8 172
rosienej 16:84a017ef96f8 173 #if defined(TARGET_KL46Z)
rosienej 16:84a017ef96f8 174 _uart->D = (uint8_t)data_tx[addr_tx]; // Freescale
rosienej 16:84a017ef96f8 175 #else
okini3939 8:d4a45bba41d2 176 _uart->THR = (uint8_t)data_tx[addr_tx];
rosienej 16:84a017ef96f8 177 #endif
okini3939 0:cbff6bf41542 178 #else
okini3939 5:72039cd4c874 179 _dmx.putc(data_tx[addr_tx]);
okini3939 0:cbff6bf41542 180 #endif
okini3939 0:cbff6bf41542 181 addr_tx ++;
okini3939 0:cbff6bf41542 182 } else {
okini3939 5:72039cd4c874 183 _dmx.attach(0, Serial::TxIrq);
okini3939 0:cbff6bf41542 184 mode_tx = DMX_MODE_BEGIN;
okini3939 0:cbff6bf41542 185 is_sent = 1;
okini3939 0:cbff6bf41542 186 timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
okini3939 0:cbff6bf41542 187 }
okini3939 0:cbff6bf41542 188 }
okini3939 0:cbff6bf41542 189 }
okini3939 0:cbff6bf41542 190
okini3939 0:cbff6bf41542 191 void DMX::int_rx () {
okini3939 0:cbff6bf41542 192 int flg, dat;
rosienej 16:84a017ef96f8 193 int tmp1,tmp2;
rosienej 18:6303931e4102 194 #if defined(TARGET_KL46Z)
rosienej 18:6303931e4102 195 /// looking for (7)erroneous data,(3) Framming Error, (4) Break
rosienej 16:84a017ef96f8 196 tmp1 = (_uart->S1 & (UART_S1_NF_MASK|UART_S1_FE_MASK)); // NF,FE
rosienej 16:84a017ef96f8 197 tmp2 = (_uart->S2 & UART_S2_LBKDIF_MASK); //LBKDIF
rosienej 16:84a017ef96f8 198 flg = (tmp1<<1) | tmp2;
rosienej 16:84a017ef96f8 199 #else
rosienej 16:84a017ef96f8 200 flg = _uart->LSR;
rosienej 16:84a017ef96f8 201 #endif
rosienej 16:84a017ef96f8 202
okini3939 1:f0d988e15810 203 #ifdef DMX_UART_DIRECT
rosienej 16:84a017ef96f8 204 #if defined(TARGET_KL46Z)
rosienej 16:84a017ef96f8 205 dat = _uart->D; // Freescale
rosienej 16:84a017ef96f8 206 #else
okini3939 8:d4a45bba41d2 207 dat = _uart->RBR;
rosienej 16:84a017ef96f8 208 #endif
rosienej 16:84a017ef96f8 209
rosienej 16:84a017ef96f8 210
okini3939 1:f0d988e15810 211 #else
okini3939 5:72039cd4c874 212 dat = _dmx.getc();
okini3939 1:f0d988e15810 213 #endif
okini3939 0:cbff6bf41542 214
okini3939 0:cbff6bf41542 215 if (flg & ((1 << 7)|(1 << 3)|(1 << 4))) {
okini3939 0:cbff6bf41542 216 // Break Time
okini3939 15:4ea4a31c7609 217 if (addr_rx >= 24 && mode_rx == DMX_MODE_DATA) {
okini3939 0:cbff6bf41542 218 is_recived = 1;
okini3939 0:cbff6bf41542 219 }
okini3939 0:cbff6bf41542 220 mode_rx = DMX_MODE_BREAK;
okini3939 0:cbff6bf41542 221 return;
okini3939 0:cbff6bf41542 222 }
okini3939 0:cbff6bf41542 223
okini3939 0:cbff6bf41542 224 if (mode_rx == DMX_MODE_BREAK) {
okini3939 0:cbff6bf41542 225
okini3939 0:cbff6bf41542 226 // Start Code
okini3939 9:e687f321c428 227 if (dat == DMX_START_CODE) {
okini3939 0:cbff6bf41542 228 addr_rx = 0;
okini3939 0:cbff6bf41542 229 mode_rx = DMX_MODE_DATA;
okini3939 0:cbff6bf41542 230 } else {
okini3939 0:cbff6bf41542 231 mode_rx = DMX_MODE_ERROR;
okini3939 0:cbff6bf41542 232 }
okini3939 0:cbff6bf41542 233
okini3939 0:cbff6bf41542 234 } else
okini3939 0:cbff6bf41542 235 if (mode_rx == DMX_MODE_DATA) {
okini3939 0:cbff6bf41542 236
okini3939 0:cbff6bf41542 237 // Data
okini3939 0:cbff6bf41542 238 data_rx[addr_rx] = dat;
okini3939 0:cbff6bf41542 239 addr_rx ++;
okini3939 0:cbff6bf41542 240
okini3939 0:cbff6bf41542 241 if (addr_rx >= DMX_SIZE) {
okini3939 0:cbff6bf41542 242 is_recived = 1;
okini3939 0:cbff6bf41542 243 mode_rx = DMX_MODE_BEGIN;
okini3939 0:cbff6bf41542 244 }
okini3939 0:cbff6bf41542 245 }
okini3939 0:cbff6bf41542 246 }
okini3939 0:cbff6bf41542 247
okini3939 4:dd0544c80096 248 void DMX::start () {
okini3939 4:dd0544c80096 249 if (mode_tx == DMX_MODE_STOP) {
okini3939 4:dd0544c80096 250 mode_tx = DMX_MODE_BEGIN;
okini3939 4:dd0544c80096 251 is_sent = 0;
okini3939 4:dd0544c80096 252 timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
okini3939 4:dd0544c80096 253 }
okini3939 4:dd0544c80096 254 }
okini3939 4:dd0544c80096 255
okini3939 4:dd0544c80096 256 void DMX::stop () {
okini3939 5:72039cd4c874 257 _dmx.attach(0, Serial::TxIrq);
okini3939 3:2eb66b4d99bd 258 timeout01.detach();
okini3939 4:dd0544c80096 259 mode_tx = DMX_MODE_STOP;
okini3939 3:2eb66b4d99bd 260 }
okini3939 12:1f176eee2d28 261
okini3939 12:1f176eee2d28 262 void DMX::clear () {
okini3939 12:1f176eee2d28 263 int i;
okini3939 12:1f176eee2d28 264
okini3939 12:1f176eee2d28 265 for (i = 0; i < DMX_SIZE; i ++) {
okini3939 12:1f176eee2d28 266 data_tx[i] = 0;
okini3939 12:1f176eee2d28 267 data_rx[i] = 0;
okini3939 12:1f176eee2d28 268 }
okini3939 12:1f176eee2d28 269 }