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