Full Version : OddBudMan's DMX Receiver (GCC)
avr >>C PROGRAMMING (AVR) >>OddBudMan's DMX Receiver (GCC)


Admin3- 04-18-2006
DMX receiving is a sinch.

Have a counter count the bytes as they come in at 250k. If you have an error (this is caused by a break in the dmx frame) reset your counter. Remember DMX spits out up to 512 channels at a time (+ start byte).

Here is some code I wrote in AVR-GCC.
This generates software PWM to dim LEDs from the input DMX signal.

CODE

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define sei()   __asm__ __volatile__ ("sei" ::)
#define cli()   __asm__ __volatile__ ("cli" ::)
#define NOP()   __asm__ __volatile__ ("nop" ::)
void wait(int);
void init_usart(void);

volatile int count,bytecount;
volatile int count,dmxcount,ch1,ch2,ch3,ch4,ch5,ch6;
volatile int i,j,k,ij;

SIGNAL (SIG_OVERFLOW0) /* Note [2] */
{
uint8_t temp=0x00;
if(count>=255)count=0;  //8bit counter
if(count<ch1)temp|=0x01; //Channel 1
if(count<ch2)temp|=0x02; //Channel 2
if(count<ch3)temp|=0x04; //Channel 3
if(count<ch4)temp|=0x08; //Channel 4
if(count<ch5)temp|=0x10; //Channel 5
if(count<ch6)temp|=0x20; //Channel 6
count++;
PORTB=temp;
//PORTB=0x00;
}


SIGNAL (SIG_UART_RECV)
{
  uint8_t status, data;
  status=UCSRA;
 data=UDR;
 
 //Frame error | DOR error detects a break and resets dmx count
 if(status&0x10){dmxcount=0;return;}
 if(status&0x08){dmxcount=0;return;}

 //check for start condition
 if(dmxcount==0){
   if(data==0){dmxcount++;return;}
 }

//  if(dmxcount==4)PORTB=~data;
 if(dmxcount==1)ch1=data;
 if(dmxcount==2)ch2=data;
 if(dmxcount==3)ch3=data;
 if(dmxcount==4)ch4=data;
 if(dmxcount==5)ch5=data;
 if(dmxcount==6)ch6=data;
 dmxcount++;
}


void ioinit (void) /* Note [5] */
{
 DDRB=0xff;   //portb as output
   
  /*Timer Interrput Settings
   * prescaller at /256    */
  TCCR0=0x01;    
  TIMSK|=0x01;
}

int main (void)
{
 ioinit();
 init_usart();
  sei ();      //turn on global interrupt
 PORTB=0xff;
  while(1){i=0;}
 return 1;
}

void init_usart(void) {
 //USART Control and Status Register A   UCSRA - Not used in init
   
  //USART Control and Status Register B   UCSRB
  /*
  Bit 7   RXCIE: RX Complete Interrupt Enable         1
  Bit 6   TXCIE: TX Complete Interrupt Enable         0
  Bit 5   UDRIE: USART Data Register Empty Interrupt Enable   0
  Bit 4   RXEN: Receiver Enable               1
  Bit 3   TXEN: Transmitter Enable            1    
  Bit 2   UCSZ2: Character Size               0
  Bit 1   RXB8: Receive Data Bit 8            0
  Bit 0   TXB8: Transmit Data Bit 8            0
  */
  UCSRB = 0x98;

  /*USART Control and Status Register C   UCSRC
  Bit 7   URSEL: Register Select      1
  Bit 6   UMSEL: USART Mode Select   0
  Bit 5               0
  Bit 4   UPM1:0: Parity Mode      0
  Bit 3   USBS: Stop Bit Select      1         //2 stop bits
  Bit 2   UCSZ1:0: Character Size      1
  Bit 1                1
  Bit 0   UCPOL: Clock Polarity      0
  */
  UCSRC=0x8e;
   
  /* 250kbps 8N2 */    
  UBRRH=0x00;
 //UBRRL=1;
  UBRRL=1;
}




DISCLAIMER: I wrote this code a little while ago now, so please be kind to my coding techniques shown in this sloppy example. I'm not even sure this will work straight off the bat but I think it should (as another poster mentioned things have changed of late with Start Byte codes, so this code is by no means 100% reliable - check the latest DMX spec revision [if you can find it...]). Hopefully this example can help others.

oddbudman


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.