DMX512, RDM send/recv library http://mbed.org/users/okini3939/notebook/dmx512
Dependents: dmx_test ArtNodeLED SPK-DVIMXR SPK-DMXer ... more
RDM.cpp
00001 /* 00002 * DMX512, RDM send/recv library 00003 * Copyright (c) 2017 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 #ifdef RDM_ENABLE 00015 00016 #define htons(n) __REV16(n) 00017 #define ntohs(n) __REV16(n) 00018 #define htonl(n) __REV(n) 00019 #define ntohl(n) __REV(n) 00020 00021 static unsigned char uid_broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 00022 00023 void DMX::pollRdm () { 00024 int i, len, crc, forMe, forGrp, forAll; 00025 struct RDM_DATA *rdm = (struct RDM_DATA *)data_rx; 00026 00027 if (!is_rdm_received) return; 00028 is_rdm_received = 0; 00029 if (rdm->Length < 24) return; 00030 00031 len = rdm->DataLength; 00032 crc = (rdm->Data[len] << 8) | rdm->Data[len + 1]; 00033 if (calcCrc(data_rx, rdm->Length - 1) != crc) return; 00034 00035 forMe = memcmp(rdm_uid, rdm->DestID, 6) == 0 ? 1 : 0; 00036 forGrp = (rdm_uid[0] == rdm->DestID[0] && rdm_uid[1] == rdm->DestID[1] && memcmp(&rdm_uid[2], uid_broadcast, 4) == 0) ? 1 : 0; 00037 forAll = memcmp(rdm_uid, uid_broadcast, 6) == 0 ? 1 : 0; 00038 00039 switch (rdm->CmdClass) { 00040 case E120_DISCOVERY_COMMAND: 00041 switch (ntohs(rdm->Parameter)) { 00042 case E120_DISC_UNIQUE_BRANCH: 00043 if (rdm->DataLength == 12 && !rdm_mute) { 00044 if (memcmp(rdm_uid, &rdm->Data[0], 6) >= 0 && memcmp(rdm_uid, &rdm->Data[6], 6) <= 0) { 00045 sendRdmDiscResponse(rdm); 00046 } 00047 } 00048 break; 00049 00050 case E120_DISC_MUTE: 00051 case E120_DISC_UN_MUTE: 00052 if (forMe || forGrp || forAll) { 00053 if (rdm->CmdClass == E120_DISC_MUTE) { 00054 rdm_mute = 1; 00055 } else { 00056 rdm_mute = 0; 00057 } 00058 if (forMe) sendRdmDiscMuteResponse(rdm); 00059 } 00060 break; 00061 00062 } 00063 break; 00064 00065 case E120_DISCOVERY_COMMAND_RESPONSE: 00066 switch (ntohs(rdm->Parameter)) { 00067 case E120_DISC_MUTE: 00068 case E120_DISC_UN_MUTE: 00069 if (forMe && memcmp(found_uid, rdm->SourceID, 6) == 0) { 00070 if (buf_uid_size && buf_uid_count < buf_uid_size) { 00071 memcpy(&buf_uid[6 * buf_uid_count], rdm->SourceID, 6); 00072 buf_uid_count ++; 00073 } 00074 } 00075 } 00076 break; 00077 00078 case E120_GET_COMMAND: 00079 case E120_SET_COMMAND: 00080 if ((forMe || forGrp || forAll) && cb_RdmParser) { 00081 cb_RdmParser(rdm); 00082 } 00083 break; 00084 00085 case E120_GET_COMMAND_RESPONSE: 00086 case E120_SET_COMMAND_RESPONSE: 00087 if ((forMe || forGrp || forAll) && cb_RdmParser) { 00088 cb_RdmParser(rdm); 00089 } 00090 break; 00091 } 00092 } 00093 00094 int DMX::calcCrc (unsigned char *buf, int len, int offset) { 00095 int i, crc = offset; 00096 00097 for (i = 0; i < len; i ++) { 00098 crc += buf[i]; 00099 } 00100 return crc; 00101 } 00102 00103 void DMX::rdmStart (int block) { 00104 Timer t; 00105 00106 t.start(); 00107 while (mode_rx != DMX_MODE_BEGIN && t.read_ms() < 100) { 00108 pollRdm(); 00109 } 00110 t.stop(); 00111 00112 mode_rdm = 1; 00113 mode_rx = DMX_MODE_BEGIN; 00114 mode_tx = DMX_MODE_BEGIN; 00115 is_sent = 0; 00116 is_received = 0; 00117 is_rdm_received = 0; 00118 timeout01.attach_us(this, &DMX::int_timer, RDM_TIME_DELAY); 00119 00120 if (block) { 00121 while (mode_rdm); 00122 } 00123 } 00124 00125 void DMX::rdmWaitResponse (int ms) { 00126 Timer t; 00127 00128 t.start(); 00129 while (t.read_ms() < ms && !is_rdm_received) { 00130 pollRdm(); 00131 } 00132 t.stop(); 00133 pollRdm(); 00134 } 00135 00136 int DMX::sendRdmDiscResponse (struct RDM_DATA *rdm) { 00137 int crc; 00138 unsigned char data[40]; 00139 00140 data[0] = 0xFE; 00141 data[1] = 0xFE; 00142 data[2] = 0xFE; 00143 data[3] = 0xFE; 00144 data[4] = 0xFE; 00145 data[5] = 0xFE; 00146 data[6] = 0xFE; 00147 data[7] = 0xAA; 00148 data[8] = rdm_uid[0] | 0xAA; 00149 data[9] = rdm_uid[0] | 0x55; 00150 data[10] = rdm_uid[1] | 0xAA; 00151 data[11] = rdm_uid[1] | 0x55; 00152 data[12] = rdm_uid[2] | 0xAA; 00153 data[13] = rdm_uid[2] | 0x55; 00154 data[14] = rdm_uid[3] | 0xAA; 00155 data[15] = rdm_uid[3] | 0x55; 00156 data[16] = rdm_uid[4] | 0xAA; 00157 data[17] = rdm_uid[4] | 0x55; 00158 data[18] = rdm_uid[5] | 0xAA; 00159 data[19] = rdm_uid[5] | 0x55; 00160 crc = calcCrc(&data[8], 12, 0); 00161 data[20] = ((crc >> 8) & 0xFF) | 0xAA; 00162 data[21] = ((crc >> 8) & 0xFF) | 0x55; 00163 data[22] = (crc & 0xFF) | 0xAA; 00164 data[23] = (crc & 0xFF) | 0x55; 00165 00166 wait_us(RDM_TIME_DELAY); 00167 /* 00168 do { 00169 wait_us(RDM_TIME_DELAY * (rand() / (RAND_MAX / 10))); 00170 } while (mode_rx != DMX_MODE_BEGIN); 00171 */ 00172 if (_xmit) _xmit->write(XMIT_TX); 00173 wait_us(10); 00174 for (int i = 0; i < 24; i ++) { 00175 _dmx.putc(data[i]); 00176 } 00177 while (!(_uart->LSR & (1<<6))); // TEMT 00178 if (_xmit) _xmit->write(XMIT_RX); 00179 00180 return 0; 00181 } 00182 00183 int DMX::sendRdmMsg (struct RDM_DATA *rdm, int CmdClass, unsigned char *data, int len) { 00184 int crc; 00185 struct RDM_DATA *rdm_msg = (struct RDM_DATA *)data_rdm; 00186 00187 while (mode_rdm); 00188 rdm_msgcount ++; 00189 rdm_msg->SubStartCode = E120_SC_SUB_MESSAGE; 00190 rdm_msg->Length = 24 + len; 00191 memcpy(rdm_msg->DestID, rdm->SourceID, 6); 00192 memcpy(rdm_msg->SourceID, rdm_uid, 6); 00193 rdm_msg->TransactionNo = rdm->TransactionNo; 00194 rdm_msg->ResponseType = E120_RESPONSE_TYPE_ACK; 00195 rdm_msg->MessageCount = rdm_msgcount; 00196 rdm_msg->SubDev = 0; 00197 rdm_msg->CmdClass = CmdClass; 00198 rdm_msg->Parameter = rdm->Parameter; 00199 rdm_msg->DataLength = len; 00200 if (data && len) { 00201 memcpy(rdm_msg->Data, data, len); 00202 } 00203 crc = calcCrc((unsigned char *)rdm_msg, rdm_msg->Length - 1); 00204 rdm_msg->Data[len] = (crc >> 8) & 0xFF; 00205 rdm_msg->Data[len + 1] = crc & 0xFF; 00206 00207 rdmStart(); 00208 return 0; 00209 } 00210 00211 int DMX::sendRdmMsg (unsigned char *dest, int CmdClass, int Parameter, int Type, unsigned char *data, int len, int block) { 00212 int crc; 00213 struct RDM_DATA *rdm_msg = (struct RDM_DATA *)data_rdm; 00214 00215 while (mode_rdm); 00216 rdm_transno ++; 00217 rdm_msgcount ++; 00218 rdm_msg->SubStartCode = E120_SC_SUB_MESSAGE; 00219 rdm_msg->Length = 24 + len; 00220 memcpy(rdm_msg->DestID, dest, 6); 00221 memcpy(rdm_msg->SourceID, rdm_uid, 6); 00222 rdm_msg->TransactionNo = rdm_transno; 00223 rdm_msg->ResponseType = Type; 00224 rdm_msg->MessageCount = rdm_msgcount; 00225 rdm_msg->SubDev = 0; 00226 rdm_msg->CmdClass = CmdClass; 00227 rdm_msg->Parameter = htons(Parameter); 00228 rdm_msg->DataLength = len; 00229 if (data && len) { 00230 memcpy(rdm_msg->Data, data, len); 00231 } 00232 crc = calcCrc((unsigned char *)rdm_msg, rdm_msg->Length - 1); 00233 rdm_msg->Data[len] = (crc >> 8) & 0xFF; 00234 rdm_msg->Data[len + 1] = crc & 0xFF; 00235 00236 rdmStart(block); 00237 return 0; 00238 } 00239 00240 int DMX::sendRdmDiscMuteResponse (struct RDM_DATA *rdm) { 00241 unsigned char data[2] = {0, 0}; 00242 00243 return sendRdmMsg(rdm, E120_DISCOVERY_COMMAND_RESPONSE, data, 2); 00244 } 00245 00246 void DMX::attachRdmCallback (void (*handler)(struct RDM_DATA *), char *uid) { 00247 00248 cb_RdmParser = handler; 00249 memcpy(rdm_uid, uid, 6); 00250 } 00251 00252 void DMX::int_rdm () { 00253 int flg, dat; 00254 00255 flg = _uart->LSR; 00256 dat = _dmx.getc(); 00257 00258 if (flg & ((1 << 7)|(1 << 3)|(1 << 4))) { 00259 // Conflict 00260 addr_rx = -1; 00261 return; 00262 } 00263 00264 if (addr_rx >= 0 && addr_rx < DMX_SIZE) { 00265 data_rx[addr_rx] = dat; 00266 addr_rx ++; 00267 } 00268 } 00269 00270 int DMX::sendRdmDiscMute (unsigned char *dest, int mute) { 00271 00272 while (mode_rdm); 00273 00274 int param = mute ? E120_DISC_MUTE : E120_DISC_UN_MUTE; 00275 sendRdmMsg(dest, E120_DISCOVERY_COMMAND, param ,E120_RESPONSE_TYPE_ACK_TIMER, NULL, 0, 1); 00276 rdmWaitResponse(100); 00277 return 0; 00278 } 00279 00280 int DMX::sendRdmDiscovery (uint64_t uid_begin, uint64_t uid_end) { 00281 int crc; 00282 unsigned char data[12]; 00283 00284 while (mode_rdm); 00285 00286 data[ 0] = (uid_begin >> 40) & 0xff; 00287 data[ 1] = (uid_begin >> 32) & 0xff; 00288 data[ 2] = (uid_begin >> 24) & 0xff; 00289 data[ 3] = (uid_begin >> 16) & 0xff; 00290 data[ 4] = (uid_begin >> 8) & 0xff; 00291 data[ 5] = uid_begin & 0xff; 00292 data[ 6] = (uid_end >> 40) & 0xff; 00293 data[ 7] = (uid_end >> 32) & 0xff; 00294 data[ 8] = (uid_end >> 24) & 0xff; 00295 data[ 9] = (uid_end >> 16) & 0xff; 00296 data[10] = (uid_end >> 8) & 0xff; 00297 data[11] = uid_end & 0xff; 00298 00299 _dmx.attach(this, &DMX::int_rdm, Serial::RxIrq); 00300 addr_rx = 0; 00301 sendRdmMsg(uid_broadcast, E120_DISCOVERY_COMMAND, E120_DISC_UNIQUE_BRANCH ,E120_RESPONSE_TYPE_ACK_TIMER, data, 12, 1); 00302 rdmWaitResponse(100); 00303 _dmx.attach(this, &DMX::int_rx, Serial::RxIrq); 00304 00305 if (addr_rx >= 24) { 00306 if (data_rx[0] == 0xfe && data_rx[7] == 0xaa) { 00307 crc = calcCrc(&data_rx[8], 12, 0); 00308 if (data_rx[20] == (((crc >> 8) & 0xFF) | 0xAA) && 00309 data_rx[21] == (((crc >> 8) & 0xFF) | 0x55) && 00310 data_rx[22] == ((crc & 0xFF) | 0xAA) && data_rx[23] == ((crc & 0xFF) | 0x55)) { 00311 found_uid[0] = (data_rx[ 8] & 0x55) | (data_rx[ 9] & 0xAA); 00312 found_uid[1] = (data_rx[10] & 0x55) | (data_rx[11] & 0xAA); 00313 found_uid[2] = (data_rx[12] & 0x55) | (data_rx[13] & 0xAA); 00314 found_uid[3] = (data_rx[14] & 0x55) | (data_rx[15] & 0xAA); 00315 found_uid[4] = (data_rx[16] & 0x55) | (data_rx[17] & 0xAA); 00316 found_uid[5] = (data_rx[18] & 0x55) | (data_rx[19] & 0xAA); 00317 return 1; 00318 } 00319 return -1; 00320 } 00321 return -1; 00322 } else 00323 if (addr_rx) { 00324 return -1; 00325 } 00326 00327 return 0; 00328 } 00329 00330 int DMX::rdmDiscoverySub (uint64_t uid_begin, uint64_t uid_end, int ttl) { 00331 int r; 00332 uint64_t uid_mid; 00333 00334 // printf("rdmDiscoverySub %04x %08x - %04x %08x\r\n", (int)(uid_begin>>32), (int)uid_begin, (int)(uid_end>>32), (int)uid_end); 00335 if (!ttl) return 0; 00336 ttl --; 00337 00338 r = sendRdmDiscovery(uid_begin, uid_end); 00339 if (uid_begin >= uid_end) { 00340 if (r > 0) { 00341 sendRdmDiscMute(found_uid, 1); 00342 } 00343 } else { 00344 if (r > 0) { 00345 sendRdmDiscMute(found_uid, 1); 00346 } 00347 if (r) { 00348 uid_mid = (uid_begin + uid_end) / 2; 00349 r = rdmDiscoverySub(uid_begin, uid_mid, ttl); 00350 r |= rdmDiscoverySub(uid_mid + 1, uid_end, ttl); 00351 } 00352 } 00353 return r; 00354 } 00355 00356 int DMX::rdmDiscovery (unsigned char *buf, int size) { 00357 00358 buf_uid_count = 0; 00359 buf_uid_size = size; 00360 buf_uid = buf; 00361 sendRdmDiscMute(uid_broadcast, 0); 00362 rdmDiscoverySub(0x000000000000, 0xfffffffffffe, 10); 00363 return buf_uid_count; 00364 } 00365 00366 #endif
Generated on Sat Jul 16 2022 01:56:41 by 1.7.2