??? 11/23/06 21:58 Read: times Msg Score: +1 +1 Good Answer/Helpful |
#128469 - DMX Responding to: ???'s previous message |
DMX is a strange protocol - it was adapted from the original AMX192 protocol which was like a video signal, long pulse frame, short pulse channel then analog level. Anyway, DMX frames start with a break signal which is a '0' bit for longer than 1 character time. The DMX spec outlines how wide this break signal should be, my recollection is 88uS but this was from the original spec when I wrote my code back in 1990! A normal character has a start bit,8 data bits and a stop bit - this stop bit is a '1' (also termed an idle). In the case of a break, we get a start bit, 8 data bits of '0' and the stop bit is still '0' - in this instance the stop bit appears in the uart bit RB8. If this bit is '0', it is most likely a break, if it is '1' it is a character.
The basic format of a DMX frame is: [BREAK] [0x00 for start code] [channel level]......up to 512 channel levels I just dug up my old code for a demux unit: ; ; ; CODE IS FOR INTEL 80C31 CPU @16MHZ ; ; PORT DEFINITIONS../=ACTIVE LOW ; ; P1.0 /BCD SWITCH BIT0,MUX ADDRESS 0 ; P1.1 /BCD SWITCH BIT1,MUX ADDRESS 1 ; P1.2 /BCD SWITCH BIT2,MUX ADDRESS 2 ; P1.3 /BCD SWITCH BIT3,MUX ADDRESS 3 ; P1.4 /ENABLE 100'S BCD SWITCH ; P1.5 /ENABLE 10'S BCD SWITCH ; P1.6 /ENABLE 1'S BCD SWITCH ; P1.7 /ENABLE SAMPLE & HOLD ; ; P3.0 RXD. DMX INPUT ; P3.1 TXD. NOT USED YET ; P3.2 /AMX SYNC IN ; P3.3 /START CONVERSION ON ADC ; P3.4 MUX OK LED (RED) ; P3.5 AMX RECEIVED,/DMX RECEIVED ; P3.6 /RD ; P3.7 /WR ; ADA EQU 0000H ;analog to digital to analog converter AD7569 MEM EQU 8000H ;optional external ram-not used for this code. ; ; internal ram allocation.. ; CHANNEL EQU 40H CHAN1 EQU CHANNEL+0 ;channel storage CHAN2 EQU CHANNEL+1 CHAN3 EQU CHANNEL+2 CHAN4 EQU CHANNEL+3 CHAN5 EQU CHANNEL+4 CHAN6 EQU CHANNEL+5 CHAN7 EQU CHANNEL+6 CHAN8 EQU CHANNEL+7 CHAN9 EQU CHANNEL+8 CHAN10 EQU CHANNEL+9 CHAN11 EQU CHANNEL+10 CHAN12 EQU CHANNEL+11 LODIM EQU 050H ;base channel number storage HIDIM EQU 051H TIMEOUT EQU 052H ;count for no mux timeout ; COMSTAT EQU 20H ;incoming dmx&amx status AD EQU COMSTAT.0 ;1 means AMX is being received SBRK EQU COMSTAT.1 ;1 means we got a break STRT EQU COMSTAT.2 ;1 means we have got a valid start code MUXOK EQU COMSTAT.3 ;1 means mux is ok ; ; others.. ; PCON EQU 087H ;this assembler doesn't know about PCON TOUT EQU 60 ;time out for no mux *50ms @16mhz ;TOUT EQU 30 ;time out for no mux *100mS@8 mhz TOUT1 EQU 10 ;timeout for mux input select *50mS @ 16mhz ; ORG 0000H LJMP START ;GOTO START OF CODE ; ; INTERUPT VECTORS ; ORG 0003H IRQ0 LJMP AMX ;amx receive routine ORG 000BH ; ; if timer0 rolls over, we have lost mux input ; TIM0 LJMP TIME ORG 0013H IRQ1 ;not used ORG 001BH TIM1 ;not used ORG 0023H LJMP DMX ;goto dmx routine ; ; Timer zero has timed out as we have had no mux. ; Decrement timer count and reload the timer ; If the timer count gets to zero,then we take action ; TIME DJNZ TIMEOUT,TIME1 ;dec timeout count ; timeout=0.. CLR TCON.4 ;stop timer0 CLR P3.4 ;turn off mux ok led CLR SBRK ;reset comms system CLR STRT ;clear start status CLR MUXOK ;mux is definitely not ok CPL AD ;goto alternate input JB AD,GAMX ;setup amx for input ; ; setup dmx for input ; MOV TIMEOUT,#TOUT1 ;reload select timeout CLR P3.5 ;turn off AMX led MOV IE,#092H ;start DMX SJMP TIME1 ; ; setup amx for input ; GAMX MOV TIMEOUT,#TOUT1 ;reload select timeout SETB P3.5 ;turn on AMX led MOV IE,#83H ;start AMX SJMP TIME1 ; ; TEX RETI TIME1 CLR TCON.4 ;stop timer MOV TL0,#00 MOV TH0,#00 ;reload timer0 SETB TCON.4 ;start timer0 RETI ; ; the show starts here... ; START MOV IE,#00 ;turn off all ints MOV R0,#CHANNEL ;setup channel pointer MOV P1,#0FFH ;disable s/h ACALL READSW ;read switches,set dimmer base number CLR P3.4 ;turn off MUX-OK led CLR P3.5 ;turn off AMX/DMX led MOV TMOD,#31H ;setup timer0 MOV TCON,#01 ;stop timers,select edge detect for int0 MOV IP,#10H ;set serial int to higher priority MOV SCON,#90H ;set serial port to mode 2 ; MOV PCON,#80H ;set to divide by clk by 32,baud rate=250kbs MOV PCON,#00H ;set to divide clk by 64,baud rate=250kbs @16mhz MOV DPTR,#ADA ;DPTR->analog converter ; ; setup interupts,clear channel levels and go! ; MOV IE,#00 ;stop everything!! MOV TIMEOUT,#TOUT1 ;load select timeout CLR TCON.4 ;stop timer0 MOV TH0,#00 MOV TL0,#00 ;reload timer0 SETB TCON.4 ;start timer0 MOV COMSTAT,#00 ;clear comms status MOV A,#00 ;clear Acc MOV R0,#CHANNEL ;clear channel storage CCHAN MOV @R0,A ;clear channel INC R0 ;goto next CJNE R0,#(CHAN12+1),CCHAN ;check for last channel MOV IE,#82H ;enable timer0 ints ; ; ; we should be receiving DMX or AMX by this point.. ; even if we're not,output the channel levels to the sample & holds ; GO MOV R7,#250 ;do 250 outputs till we update OUTCHAN MOV R1,#CHANNEL ;R1->channels CLOOP MOV A,@R1 ;get channel level MOVX @DPTR,A ;output it to the dac MOV A,R1 ;channel into a ANL A,#0FH ;only the lower 4 bits for mux address ORL A,#0F0H ;set switch enable bits MOV P1,A ;output mux address CLR P1.7 ;enable s/h NOP ;allow capacitor to charge to channel level NOP SETB P1.7 ;disable s/h INC R1 ;next channel CJNE R1,#(CHAN12+1),CLOOP ;see if its the last channel DJNZ R7,OUTCHAN ;output 100 times then update dimmer base etc. ; ; update dimmer base number & see if mux is still ok ; LCALL READSW ;read dimmer base number from switches JB MUXOK,GO ;keep on outputting channels if muxok ; ; NO MUX SIGNAL RECEIVED ; MOV A,#00 ;clear A MOV R0,#CHANNEL ;R0->CHANNELS CCLOOP MOV @R0,A ;clear channel level INC R0 ;next channel CJNE R0,#(CHAN12+1),CCLOOP ;until all channels done SJMP GO ;look for input again ; ; read dimmer base number switches and store them into lodim &hidim ; we also kick the watchdog whilst doing this ; READSW MOV R6,#00 ;R6 has dimmer base hi MOV R7,#00 ;R7 has dimmer base low ; ; GET 100'S SWITCH SETTING ; MOV P1,#0FFH ;set bits high(input),& disable s/h CLR P1.4 ;enable 100's switch MOV A,P1 ;read switch setting CPL A ;invert it (hardware thing) ANL A,#0FH ;we only want low 4 bits MOV B,#100 ;multiply it by 100 MUL AB ;result in b(hi) A(low) ADD A,R7 ;add into base number low MOV R7,A ;save result into base num low MOV A,B :get msb of multiply into a ADDC A,R6 ;add into base number hi MOV R6,A ;save into dimmer base number SETB P1.4 ;turn off 100s switch ; ; GET 10'S SWITCH SETTING ; CLR P1.5 ;enable 10's switch MOV A,P1 ;read switch CPL A ;invert it ANL A,#0FH ;mask for low 4 bits MOV B,#10 ;multiply by 10 MUL AB ;result in b(hi),A(low) ADD A,R7 ;add to dimmer base number MOV R7,A ;save result into dimmer base number CLR A ;A=0. we never get a result above 90 dec ADDC A,R6 ;add in the carry (if any) MOV R6,A ;save into dimmer base number SETB P1.5 ;turn off 10's switch ; ; GET 1'S SWITCH SETTING ; CLR P1.6 ;turn on units switch MOV A,P1 ;read switch CPL A ;turn it upside down ANL A,#0FH ;lower nibble only ADD A,R7 ;add into dimmer base number MOV R7,A ;save it MOV A,#00 ;add in carry (if any) ADDC A,R6 ; MOV R6,A ;save it ; ; MINUS 1 TO CORRECT THINGS ; CLR C ;clear borrow(carry) MOV A,R7 ;get dimmber base low SUBB A,#1 ;minus 1 MOV R7,A ;save result MOV A,R6 ;get dimmber base hi SUBB A,#00 ;subtract borrow (if any) MOV R6,A ;save it ; ; UPDATE GLOBAL DIMMBER BASE NUMBER ; CLR IE.7 ;stop interupts for a tick MOV LODIM,R7 MOV HIDIM,R6 SETB IE.7 ;start interupts again... RET ; ; dmx reception routine. ; DMX PUSH 0D0H ;save PSW CLR SCON.0 ;reset recv int CLR SCON.1 ;reset tx int MOV R2,SBUF ;read receive date into A JNB SCON.2,BRKORBAD ;IF RECV BIT8=0,EITHER A BREAK OR OVERRUN ; ; received char must be good then.. ; JB SBRK,BROK ;jump if we've received a break POP 0D0H ;restore PSW RETI ;we haven't got a break yet,do nothing ; BROK JB STRT,STOK ;jump if we've got a good start code ; ; we haven't yet received a start code,check for byte=00 ; CJNE R2,#00,BADST ;jump if we got a bad start code ; ; start code is good,set start flag ; SETB STRT ;set start code ok flag POP 0D0H ;restore PSW RETI ; ; start code was bad,go back to looking for a break ; BADST CLR SBRK ;no break CLR STRT ;just in case POP 0D0H ;restore PSW RETI ; ; we've already got a break and a start code ; figure out if we want this channel.. ; ; on break we load channel countdown with our dimmer base number ; on each dimmer level received,we decrement this count ; upon reaching zero,we then grab the next 12 channels ; and put them into ram ; STOK CJNE R4,#00,CDEC ;SEE IF CHANNEL COUNTDOWN HI=0 CJNE R3,#00,CDEC ;see if channel countdown low=0 ; ; the countdown=0,time to grab the channels we want. ; CJNE R0,#(CHAN12+1),GETCHAN ;compare channel count with last channel ; ; we've got all the channels we want,so discard all others ; POP 0D0H ;restore PSW RETI ; ; decrement the channel countdown ; CDEC CJNE R3,#00,COUNTHI ;R3=00? DEC R3 ;decrement count low CJNE R4,#00,COUNTZ ;jump if count hi=0 POP 0D0H ;restore PSW RETI ;if R4=00 return COUNTZ DEC R4 POP 0D0H ;restore PSW RETI ; COUNTHI DEC R3 ;decrement count low POP 0D0H ;restore PSW RETI ; ; channel countdown=0 and we haven't got all our channels yet ; GETCHAN JC GTCHAN1 ;R0<=CHAN12 POP 0D0H ;restore PSW RETI ;R0>CHAN12 ; GTCHAN1 PUSH 0E0H ;save accumulator MOV A,R2 ;get channel level into A MOV @R0,A ;move received channel to ram INC R0 ;R0->next channel POP 0E0H ;restore accumulator POP 0D0H ;restore PSW RETI ; ; now we process either data overrun or break ; BRKORBAD MOV R5,#8 ;number of loops =4@8mhz,=8 @16mhz ; see if RxD changes within 30 us. If it does,there ; was a data overrun error,else it must be a break ; LOOP JB P3.0,OVER ;jump if RxD changes DJNZ R5,LOOP ;try again until R5=0 ; ; must be a break,as RxD has been marking >88us ; CLR STRT ;so that we look for a start code SETB SBRK ;we got a break SETB MUXOK SETB P3.4 ;Turn on MUX-OK led MOV TIMEOUT,#TOUT ;reload timeout CLR TCON.4 ;stop timer 0 MOV TL0,#00 MOV TH0,#00 ;reload timer0 SETB TCON.4 ;start timer0 MOV R0,#CHAN1 ;reset channel pointer MOV R4,HIDIM ;reload countdown MOV R3,LODIM ;with dimmer base number POP 0D0H ;restore PSW RETI ; ; data must have overrun ; OVER CLR STRT ;go back to looking for a CLR SBRK ;break/start code POP 0D0H ;restore PSW RETI ; ; AMX reception routine. ; AMX NOP ;delay 6us @ 16mhz NOP NOP NOP NOP NOP NOP NOP NOP ;delay 6 us @ 16mhz NOP NOP NOP NOP NOP NOP NOP NOP ;delay 6us @ 16mhz NOP NOP NOP NOP NOP NOP NOP NOP ;delay 6 us @ 16mhz NOP NOP NOP NOP NOP NOP NOP JB P3.2,GETAMX ;if sync=1 must be a channel sync ; ; sync must still be low, frame sync it is ; CLR STRT ;so that we look for a start code SETB SBRK ;we got a break(frame sync) SETB P3.4 ;Turn on MUX-OK led SETB MUXOK ;MUX is ok MOV TIMEOUT,#TOUT ;reload timeout CLR TCON.4 ;stop timer 0 MOV TL0,#00 MOV TH0,#00 ;reload timer0 SETB TCON.4 ;start timer0 MOV R0,#CHAN1 ;reset channel pointer MOV R4,HIDIM ;reload countdown MOV R3,LODIM ;with dimmer base number RETI ; ; we got a channel sync ; GETAMX CLR P3.3 ;start analog->digital conversion SETB P3.3 NOP ;wait 3us approx NOP NOP NOP PUSH 0D0H ;push psw PUSH 0E0H ;push acc MOVX A,@DPTR ;read adc value JB SBRK,ASTOK ;we've already got the frame sync ; discard level until we've got frame sync POP 0E0H ;restore accumulator POP 0D0H ;restore psw RETI ; ; on break we load channel countdown with our dimmer base number ; on each dimmer level received,we decrement this count ; upon reaching zero,we then grab the next 12 channels ; and put them into ram ; ASTOK CJNE R4,#00,ACDEC ;SEE IF CHANNEL COUNTDOWN HI=0 CJNE R3,#00,ACDEC ;see if channel countdown low=0 ; ; the countdown=0,time to grab the channels we want. ; CJNE R0,#(CHAN12+1),AGETCHAN ;compare channel count with last channel ; ; we've got all the channels we want,so discard all others ; POP 0E0H ;restore accumulator POP 0D0H ;restore psw RETI ; ; decrement the channel countdown ; ACDEC CJNE R3,#00,ACOUNTHI ;R3=00? DEC R3 ;decrement count low CJNE R4,#00,ACOUNTZ ;jump if count hi=0 POP 0E0H ;restore accumulator POP 0D0H ;restore PSW RETI ACOUNTZ DEC R4 POP 0E0H ;restore accumulator POP 0D0H ;restore psw RETI ; ACOUNTHI DEC R3 ;decrement count low POP 0E0H ;restore accumulator POP 0D0H ;restore psw RETI ; channel countdown=0 and we haven't got all our channels yet ; AGETCHAN JC AGTCHAN1 ;R0<=CHAN12 POP 0E0H ;R0>CHAN12 POP 0D0H ;restore psw RETI AGTCHAN1 MOV @R0,A ;move received channel to ram INC R0 ;R0->next channel POP 0E0H ;restore accumulator POP 0D0H ;restore psw RETI END |
Topic | Author | Date |
Kathy Quinlan's DMX | 01/01/70 00:00 | |
I guess... | 01/01/70 00:00 | |
Any help? | 01/01/70 00:00 | |
Any help? | 01/01/70 00:00 | |
DMX![]() | 01/01/70 00:00 |