RDM 接收端代码


  1 /*******************************************************************************
  2 * Types and defines
  3 ******************************************************************************/
  4 
  5 //#define VALIDATE_PERFORMANCE_ON_MAX_DMX_BUS_LOAD
  6 
  7 #define MAN_ID ((32*32*('N'-'@')) + (32*('X'-'@')) + ('P'-'@'))
  8 
  9 #define DEVICE_MODEL_ID1 0x00 /* MSB */
 10 #define DEVICE_MODEL_ID0 0x01 /* LSB */
 11 
 12 #define SW_VERSION_ID3 0x01 /* MSB */
 13 #define SW_VERSION_ID2 0x00
 14 #define SW_VERSION_ID1 0x00
 15 #define SW_VERSION_ID0 0x03 /* LSB */
 16 #define FIRMWARE_VERSION "V1.0.0.3"
 17 
 18 #define DMX512_FOOTPRINT 4 /* nr of slots this device uses */
 19 
 20 #define SC_NULL 0x00 /* NULL Start Code Packet */
 21 #define SC_TEXT 0x17 /* Start Code ASCII Text Packet */
 22 #define SC_RDM 0xCC /* Start Code RDM Packet */
 23 
 24 #define SC_SUB_MESSAGE 0x01
 25 
 26 // RDM command classes (Slot 20)
 27 #define DISCOVERY_COMMAND 0x10
 28 #define DISCOVERY_COMMAND_RESPONSE 0x11
 29 #define GET_COMMAND 0x20
 30 #define GET_COMMAND_RESPONSE 0x21
 31 #define SET_COMMAND 0x30
 32 #define SET_COMMAND_RESPONSE 0x31
 33 
 34 #define RESPONSE_TYPE_ACK 0x00
 35 #define RESPONSE_TYPE_ACK_TIMER 0x01
 36 #define RESPONSE_TYPE_NACK_REASON 0x02
 37 #define RESPONSE_TYPE_ACK_OVERFLOW 0x03
 38 
 39 #define DISC_UNIQUE_BRANCH 0x0001
 40 #define DISC_MUTE 0x0002
 41 #define DISC_UN_MUTE 0x0003
 42 #define DEVICE_INFO 0x0060
 43 #define SOFTWARE_VERSION_LABEL 0x00C0
 44 #define DMX_START_ADDRESS 0x00F0
 45 #define IDENTIFY_DEVICE 0x1000
 46 
 47 /*******************************************************************************
 48 * global variables
 49 ******************************************************************************/
 50 
 51 static uint16_t my_dmx_start_address;
 52 
 53 #ifdef SUPPORT_RDM_OVER_DMX512
 54 static uint32_t my_unique_id;
 55 static long long my_uid;
 56 static uint16_t break_time;
 57 static uint16_t mab_time;
 58 static uint8_t rdm_message_count;
 59 static uint8_t rdm_response_msg[64];
 60 static uint8_t identify_state; // off=0, on=1
 61 #endif
 62 
 63 /*******************************************************************************
 64 * local functions
 65 ******************************************************************************/
 66 
 67 static uint16_t get_my_slot_nrs(void)
 68 {
 69 return ((bsp_read_dip_switches() * 32) + 29);
 70 }
 71 
 72 static inline void init_globals(void)
 73 {
 74 my_dmx_start_address = get_my_slot_nrs();
 75 #ifdef SUPPORT_RDM_OVER_DMX512
 76 my_unique_id = bsp_get_id(); // this is not garanteed to be unique !!
 77 my_uid = ((MAN_ID >> 8) & 0xFF);
 78 my_uid <<= 8;
 79 my_uid |= ((MAN_ID >> 0) & 0xFF);
 80 my_uid <<= 8;
 81 my_uid |= ((my_unique_id >> 24) & 0xFF);
 82 my_uid <<= 8;
 83 my_uid |= ((my_unique_id >> 16) & 0xFF);
 84 my_uid <<= 8;
 85 my_uid |= ((my_unique_id >> 8) & 0xFF);
 86 my_uid <<= 8;
 87 my_uid |= ((my_unique_id >> 0) & 0xFF);
 88 break_time = 176; /* 176 usec */
 89 mab_time = 12; /* 12 usec */
 90 rdm_message_count = 0;
 91 identify_state = 0;
 92 #endif
 93 }
 94 
 95 #ifdef SUPPORT_RDM_OVER_DMX512
 96 static uint16_t calc_crc(uint8_t *data, uint8_t len)
 97 {
 98 uint16_t crc = 0;
 99 uint16_t i;
100 
101 for (i=0; i < len; i++)
102 {
103 crc += *data++;
104 }
105 return crc;
106 }
107 
108 static inline void send_disc_response(uint8_t *rdm_msg)
109 {
110 bsp_delay_usec(100);
111 rdm_response_msg[0] = 0xFE;
112 rdm_response_msg[1] = 0xFE;
113 rdm_response_msg[2] = 0xFE;
114 rdm_response_msg[3] = 0xFE;
115 rdm_response_msg[4] = 0xFE;
116 rdm_response_msg[5] = 0xFE;
117 rdm_response_msg[6] = 0xFE;
118 rdm_response_msg[7] = 0xAA;
119 rdm_response_msg[8] = ((MAN_ID >> 8) & 0xFF) | 0xAA;
120 rdm_response_msg[9] = ((MAN_ID >> 8) & 0xFF) | 0x55;
121 rdm_response_msg[10] = ((MAN_ID >> 0) & 0xFF) | 0xAA;
122 rdm_response_msg[11] = ((MAN_ID >> 0) & 0xFF) | 0x55;
123 rdm_response_msg[12] = ((my_unique_id >> 24) & 0xFF) | 0xAA;
124 rdm_response_msg[13] = ((my_unique_id >> 24) & 0xFF) | 0x55;
125 rdm_response_msg[14] = ((my_unique_id >> 16) & 0xFF) | 0xAA;
126 rdm_response_msg[15] = ((my_unique_id >> 16) & 0xFF) | 0x55;
127 rdm_response_msg[16] = ((my_unique_id >> 8) & 0xFF) | 0xAA;
128 rdm_response_msg[17] = ((my_unique_id >> 8) & 0xFF) | 0x55;
129 rdm_response_msg[18] = ((my_unique_id >> 0) & 0xFF) | 0xAA;
130 rdm_response_msg[19] = ((my_unique_id >> 0) & 0xFF) | 0x55;
131 uint16_t crc = calc_crc(&rdm_response_msg[8], 12);
132 rdm_response_msg[20] = ((crc >> 8) & 0xFF) | 0xAA;
133 rdm_response_msg[21] = ((crc >> 8) & 0xFF) | 0x55;
134 rdm_response_msg[22] = ((crc >> 0) & 0xFF) | 0xAA;
135 rdm_response_msg[23] = ((crc >> 0) & 0xFF) | 0x55;
136 bsp_xmit_to_dmx_bus();
137 Uart_XmitDmxSlotValues(rdm_response_msg, 24, 0/*NO BREAK*/, 4, true);
138 bsp_recv_from_dmx_bus();
139 }
140 
141 static void send_rdm_msg(uint8_t *rdm_msg, uint8_t command_class, uint8_t data_len)
142 {
143 uint8_t count = 24 + data_len;
144 
145 // Remark: Parameter Data must be filled by the caller of this function
146 bsp_delay_usec(150);
147 rdm_response_msg[0] = SC_RDM;
148 rdm_response_msg[1] = SC_SUB_MESSAGE;
149 rdm_response_msg[2] = count;
150 rdm_response_msg[3] = rdm_msg[9]; // copy destination from received msg
151 rdm_response_msg[4] = rdm_msg[10];
152 rdm_response_msg[5] = rdm_msg[11];
153 rdm_response_msg[6] = rdm_msg[12];
154 rdm_response_msg[7] = rdm_msg[13];
155 rdm_response_msg[8] = rdm_msg[14];
156 rdm_response_msg[9] = ((MAN_ID >> 8) & 0xFF);
157 rdm_response_msg[10] = ((MAN_ID >> 0) & 0xFF);
158 rdm_response_msg[11] = ((my_unique_id >> 24) & 0xFF);
159 rdm_response_msg[12] = ((my_unique_id >> 16) & 0xFF);
160 rdm_response_msg[13] = ((my_unique_id >> 8) & 0xFF);
161 rdm_response_msg[14] = ((my_unique_id >> 0) & 0xFF);
162 rdm_response_msg[15] = rdm_msg[15]; // pass back Transaction Number
163 rdm_response_msg[16] = RESPONSE_TYPE_ACK;
164 rdm_response_msg[17] = rdm_message_count;
165 rdm_response_msg[18] = 0; // Sub-Device MSB
166 rdm_response_msg[19] = 0; // Sub-Device LSB
167 rdm_response_msg[20] = command_class;
168 rdm_response_msg[21] = rdm_msg[21]; // copy PID from received msg
169 rdm_response_msg[22] = rdm_msg[22];
170 rdm_response_msg[23] = data_len;
171 uint16_t crc = calc_crc(rdm_response_msg, count);
172 rdm_response_msg[count+0] = (crc >> 8) & 0xFF;
173 rdm_response_msg[count+1] = (crc >> 0) & 0xFF;
174 bsp_xmit_to_dmx_bus();
175 Uart_XmitDmxSlotValues(rdm_response_msg, (count + 2),
176 break_time, mab_time, true);
177 bsp_recv_from_dmx_bus();
178 }
179 
180 static inline void send_disc_mute_response(uint8_t *rdm_msg)
181 {
182 // no binding uid, only the control field
183 rdm_response_msg[24] = 0;
184 rdm_response_msg[25] = 0;
185 send_rdm_msg(rdm_msg, DISCOVERY_COMMAND_RESPONSE, 2);
186 }
187 
188 static inline void send_disc_un_mute_response(uint8_t *rdm_msg)
189 {
190 send_disc_mute_response(rdm_msg);
191 }
192 
193 static inline void send_get_device_info_response(uint8_t *rdm_msg)
194 {
195 rdm_response_msg[24] = 0x01; // RDM Protocol Version MSB
196 rdm_response_msg[25] = 0x00; // RDM Protocol Version LSB
197 rdm_response_msg[26] = DEVICE_MODEL_ID1;
198 rdm_response_msg[27] = DEVICE_MODEL_ID0;
199 rdm_response_msg[28] = 0x01; // Product Category MSB
200 rdm_response_msg[29] = 0x01; // Product Category LSB
201 rdm_response_msg[30] = SW_VERSION_ID3;
202 rdm_response_msg[31] = SW_VERSION_ID2;
203 rdm_response_msg[32] = SW_VERSION_ID1;
204 rdm_response_msg[33] = SW_VERSION_ID0;
205 rdm_response_msg[34] = 0x00; // DMX512 Footprint MSB
206 rdm_response_msg[35] = DMX512_FOOTPRINT;
207 rdm_response_msg[36] = 0x01; // DMX512 Personality MSB
208 rdm_response_msg[37] = 0x01; // DMX512 Personality LSB
209 rdm_response_msg[38] = (my_dmx_start_address >> 8) & 0xFF; // DMX512 Start Address MSB
210 rdm_response_msg[39] = (my_dmx_start_address >> 0) & 0xFF; // DMX512 Start Address LSB
211 rdm_response_msg[40] = 0x00; // Sub-Device Count MSB
212 rdm_response_msg[41] = 0x00; // Sub-Device Count LSB
213 rdm_response_msg[42] = 0x00; // Sensor Count
214 send_rdm_msg(rdm_msg, GET_COMMAND_RESPONSE, 19);
215 }
216 
217 static inline void send_get_software_version_response(uint8_t *rdm_msg)
218 {
219 rdm_response_msg[24] = 'N';
220 rdm_response_msg[25] = 'X';
221 rdm_response_msg[26] = 'P';
222 rdm_response_msg[27] = ' ';
223 rdm_response_msg[28] = 'L';
224 rdm_response_msg[29] = 'P';
225 rdm_response_msg[30] = 'C';
226 rdm_response_msg[31] = '1';
227 rdm_response_msg[32] = '1';
228 rdm_response_msg[33] = '1';
229 rdm_response_msg[34] = '4';
230 rdm_response_msg[35] = ' ';
231 rdm_response_msg[36] = 'D';
232 rdm_response_msg[37] = 'M';
233 rdm_response_msg[38] = 'X';
234 rdm_response_msg[39] = '5';
235 rdm_response_msg[40] = '1';
236 rdm_response_msg[41] = '2';
237 rdm_response_msg[42] = ' ';
238 rdm_response_msg[43] = 's';
239 rdm_response_msg[44] = 'l';
240 rdm_response_msg[45] = 'a';
241 rdm_response_msg[46] = 'v';
242 rdm_response_msg[47] = 'e';
243 send_rdm_msg(rdm_msg, GET_COMMAND_RESPONSE, 24);
244 }
245 
246 static inline void send_get_dmx_start_address_response(uint8_t *rdm_msg)
247 {
248 rdm_response_msg[24] = (my_dmx_start_address >> 8) & 0xFF;
249 rdm_response_msg[25] = (my_dmx_start_address >> 0) & 0xFF;
250 send_rdm_msg(rdm_msg, GET_COMMAND_RESPONSE, 2);
251 }
252 
253 static inline void send_get_identify_device_response(uint8_t *rdm_msg, uint8_t state)
254 {
255 rdm_response_msg[24] = state;
256 send_rdm_msg(rdm_msg, GET_COMMAND_RESPONSE, 1);
257 }
258 
259 static inline void send_set_dmx_start_address_response(uint8_t *rdm_msg)
260 {
261 send_rdm_msg(rdm_msg, SET_COMMAND_RESPONSE, 0);
262 }
263 
264 static inline void send_set_identify_device_response(uint8_t * rdm_msg)
265 {
266 send_rdm_msg(rdm_msg, SET_COMMAND_RESPONSE, 0);
267 }
268 
269 static inline bool check_broadcast(uint8_t * msg)
270 {
271 if ((msg[5] == 0xFF) && (msg[6] == 0xFF) &&
272 (msg[7] == 0xFF) && (msg[8] == 0xFF))
273 {
274 if (((msg[3] == 0xFF) && (msg[4] == 0xFF)) ||
275 ((msg[3] == ((MAN_ID >> 8) & 0xFF)) &&
276 (msg[4] == ((MAN_ID >> 0) & 0xFF))))
277 {
278 return true;
279 }
280 }
281 return false;
282 }
283 
284 static inline bool check_own_uid(uint8_t * msg)
285 {
286 if ((msg[3] == ((MAN_ID >> 8) & 0xFF)) &&
287 (msg[4] == ((MAN_ID >> 0) & 0xFF)) &&
288 (msg[5] == ((my_unique_id >> 24) & 0xFF)) &&
289 (msg[6] == ((my_unique_id >> 16) & 0xFF)) &&
290 (msg[7] == ((my_unique_id >> 8) & 0xFF)) &&
291 (msg[8] == ((my_unique_id >> 0) & 0xFF)))
292 {
293 return true;
294 }
295 return false;
296 }
297 
298 static inline void handle_rdm_msg(uint8_t *rdm_msg)
299 {
300 static bool rdm_muted = false;
301 
302 /* check sub start code in RDM Packet and minimum lenght */
303 if ((rdm_msg[1] == SC_SUB_MESSAGE) && (rdm_msg[2] >= 24))
304 {
305 uint8_t len = rdm_msg[2];
306 uint16_t crc = ((uint16_t)rdm_msg[len+0] << 8) | rdm_msg[len+1];
307 
308 if (calc_crc(rdm_msg, len) != crc) return;
309 
310 bool broadcast = check_broadcast(rdm_msg);
311 bool own_uid = check_own_uid(rdm_msg);
312 
313 if (!broadcast && !own_uid) return;
314 
315 uint16_t pid = ((uint16_t)rdm_msg[21] << 8) | rdm_msg[22];
316 
317 /* check command class (CC) */
318 switch (rdm_msg[20])
319 {
320 case DISCOVERY_COMMAND:
321 /* check parameter ID (PID) */
322 if ((pid == DISC_UNIQUE_BRANCH) && (len == 36))
323 {
324 if (!rdm_muted)
325 {
326 long long lower_bound_uid;
327 long long upper_bound_uid;
328 
329 lower_bound_uid = rdm_msg[24];
330 lower_bound_uid <<= 8;
331 lower_bound_uid |= rdm_msg[25];
332 lower_bound_uid <<= 8;
333 lower_bound_uid |= rdm_msg[26];
334 lower_bound_uid <<= 8;
335 lower_bound_uid |= rdm_msg[27];
336 lower_bound_uid <<= 8;
337 lower_bound_uid |= rdm_msg[28];
338 lower_bound_uid <<= 8;
339 lower_bound_uid |= rdm_msg[29];
340 
341 upper_bound_uid = rdm_msg[30];
342 upper_bound_uid <<= 8;
343 upper_bound_uid |= rdm_msg[31];
344 upper_bound_uid <<= 8;
345 upper_bound_uid |= rdm_msg[32];
346 upper_bound_uid <<= 8;
347 upper_bound_uid |= rdm_msg[33];
348 upper_bound_uid <<= 8;
349 upper_bound_uid |= rdm_msg[34];
350 upper_bound_uid <<= 8;
351 upper_bound_uid |= rdm_msg[35];
352 
353 if ((my_uid >= lower_bound_uid) && (my_uid <= upper_bound_uid))
354 {
355 send_disc_response(rdm_msg);
356 }
357 }
358 }
359 else if ((pid == DISC_MUTE) && (len == 24))
360 {
361 rdm_muted = true;
362 if (own_uid) send_disc_mute_response(rdm_msg);
363 }
364 else if ((pid == DISC_UN_MUTE) && (len == 24))
365 {
366 rdm_muted = false;
367 if (own_uid) send_disc_un_mute_response(rdm_msg);
368 }
369 break;
370 case GET_COMMAND:
371 if (own_uid)
372 {
373 if ((pid == DEVICE_INFO) && (len == 24))
374 {
375 send_get_device_info_response(rdm_msg);
376 }
377 else if ((pid == SOFTWARE_VERSION_LABEL) && (len == 24))
378 {
379 send_get_software_version_response(rdm_msg);
380 }
381 else if ((pid == DMX_START_ADDRESS) && (len == 24))
382 {
383 send_get_dmx_start_address_response(rdm_msg);
384 }
385 else if ((pid == IDENTIFY_DEVICE) && (len == 24))
386 {
387 send_get_identify_device_response(rdm_msg, identify_state);
388 }
389 }
390 break;
391 case SET_COMMAND:
392 if ((pid == DMX_START_ADDRESS) && (len == 26))
393 {
394 my_dmx_start_address = ((uint16_t)rdm_msg[24] << 8) | rdm_msg[25];
395 if (own_uid) send_set_dmx_start_address_response(rdm_msg);
396 }
397 else if ((pid == IDENTIFY_DEVICE) && (len == 25))
398 {
399 identify_state = rdm_msg[24];
400 if (identify_state)
401 {
402 dim_leds(255,255,255,255);
403 #ifdef SUPPORT_I2C_BUS
404 lcd_update("You found me :-)");
405 #endif
406 }
407 else
408 {
409 dim_leds(0,0,0,0);
410 #ifdef SUPPORT_I2C_BUS
411 lcd_update("");
412 #endif
413 }
414 if (own_uid) send_set_identify_device_response(rdm_msg);
415 }
416 break;
417 default:
418 break;
419 }
420 }
421 }
422 #endif
423 
424 /*******************************************************************************
425 * global functions
426 ******************************************************************************/
427 
428 int main (void)
429 {
430 bool communication_lost = false;
431 bool not_addressed = false;
432 uint16_t dmx_len;
433 uint8_t *pslot_values;
434 uint8_t busyled_state = 0;
435 
436 SystemInit();
437 bsp_init();
438 
439 bsp_control_led(0,0); /* on startup turn on traffic led to check proper working */
440 init_globals();
441 #ifdef SUPPORT_MANUAL_CONTROL
442 init_manual_ctrl();
443 #endif
444 #ifdef SUPPORT_I2C_BUS
445 lcd_update("NXP LPC1114 DMX512 slave"); /* startup msg on LCD */
446 #endif
447 Uart_LoopBackTest(true);
448 while(1)
449 {
450 // blocking read for 1000 milli seconds
451 dmx_len = Uart_RecvDmxSlotValues(&pslot_values, true, 1000);
452 if (dmx_len > 0)
453 {
454 if (communication_lost || not_addressed)
455 {
456 communication_lost = false;
457 not_addressed = false;
458 #ifdef SUPPORT_I2C_BUS
459 if (pslot_values[0] != SC_TEXT) lcd_update("");
460 #endif
461 }
462 #ifndef VALIDATE_PERFORMANCE_ON_MAX_DMX_BUS_LOAD
463 busyled_state ^= 1;
464 bsp_control_led(0, busyled_state);
465 #endif
466 /* Check the start code */
467 if (pslot_values[0] == SC_NULL)
468 {
469 #ifndef SUPPORT_RDM_OVER_DMX512
470 my_dmx_start_address = get_my_slot_nrs();
471 #endif
472 if (dmx_len > my_dmx_start_address + 0)
473 {
474 uint8_t mySlotValues[DMX512_FOOTPRINT] = {0,0,0,0};
475 mySlotValues[0] = pslot_values[my_dmx_start_address + 0];
476 if (dmx_len > my_dmx_start_address + 1)
477 mySlotValues[1] = pslot_values[my_dmx_start_address + 1];
478 if (dmx_len > my_dmx_start_address + 2)
479 mySlotValues[2] = pslot_values[my_dmx_start_address + 2];
480 if (dmx_len > my_dmx_start_address + 3)
481 mySlotValues[3] = pslot_values[my_dmx_start_address + 3];
482 dim_leds(mySlotValues[0], mySlotValues[1],
483 mySlotValues[2], mySlotValues[3]);
484 #ifdef VALIDATE_PERFORMANCE_ON_MAX_DMX_BUS_LOAD
485 bsp_control_led(0, ~mySlotValues[3]);
486 #endif
487 }
488 else
489 {
490 not_addressed = true;
491 dim_leds(0,0,0,0);
492 #ifdef SUPPORT_I2C_BUS
493 lcd_update("Not addressed byDMX512 master");
494 #endif
495 }
496 }
497 #ifdef SUPPORT_I2C_BUS
498 else if (pslot_values[0] == SC_TEXT)
499 { /* minimal length of msg must be 4 bytes(=slots) */
500 if (dmx_len >= 4)
501 {
502 lcd_update((char *)(pslot_values+3));
503 }
504 }
505 #endif
506 #ifdef SUPPORT_RDM_OVER_DMX512
507 else if (pslot_values[0] == SC_RDM)
508 {
509 handle_rdm_msg(pslot_values);
510 }
511 #endif
512 }
513 else
514 { /* nothing received in 1 second, switch off the leds */
515 communication_lost = true;
516 #ifdef SUPPORT_RDM_OVER_DMX512
517 if (!identify_state)
518 #endif
519 {
520 dim_leds(0,0,0,0);
521 #ifdef SUPPORT_I2C_BUS
522 lcd_update("No packets from DMX512 master");
523 #endif
524 }
525 }
526 #ifdef SUPPORT_MANUAL_CONTROL
527 check_manual_ctrl();
528 #endif
529 WDT_Feed();
530 }
531 }
532 
533 void dim_leds(uint8_t value1, uint8_t value2, uint8_t value3, uint8_t value4)
534 {
535 Timer_PWM_Set_Duty_Cycle(CT16B0, CTMAT0, value1);
536 Timer_PWM_Set_Duty_Cycle(CT16B0, CTMAT1, value2);
537 Timer_PWM_Set_Duty_Cycle(CT16B1, CTMAT0, value3);
538 Timer_PWM_Set_Duty_Cycle(CT16B1, CTMAT1, value4);
539 }
540 
541 void get_version_string(char *pstr)
542 {
543 #ifdef SUPPORT_MANUAL_CONTROL
544 strcpy(pstr, FIRMWARE_VERSION);
545 #endif
546 }
547 
548 
549 /* EOF */
550 
551  

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM