Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SoftwareSerial.h>
- /*
- * dmx_ws2801_bridge.c
- *
- * Created: 6/18/2011 2:37:20 PM
- * Author: Administrator
- */
- /******************************* Addressing variable declarations *****************************/
- //#include <avr/io.h>
- //#include <WProgram.h>
- //#include <HardwareSerial.h>
- #define NUMBER_OF_CHANNELS 12
- //the number of channels we want to receive (8 by default).
- //DMX Standard signifies a new transmition with a minimum ~88us LOW break period
- //followed by a minimum ~4us HIGH Mark After Break(MAB)
- #define DMX_BREAK_MICROS 80
- #define DMX_MAB_MICROS 4
- void setupSPI();
- void spi_out_three(byte b1, byte b2, byte b3);
- void action();
- uint16_t dmxaddress = 1;
- /****************************** MAX485 variable declarations *****************************/
- #define RECEIVER_OUTPUT_ENABLE 4
- /* receiver output enable (pin2) on the max485.
- * will be left low to set the max485 to receive data. */
- #define DRIVER_OUTPUT_ENABLE 5
- /* driver output enable (pin3) on the max485.
- * will left low to disable driver output. */
- #define RX_PIN 0 // serial receive pin, which takes the incoming data from the MAX485.
- #define TX_PIN 1 // serial transmission pin
- /******************************* DMX variable declarations ********************************/
- volatile uint16_t i = 0; //dummy variable for dmxvalue[]
- volatile uint16_t j = 0;
- volatile uint8_t dmxreceived = 0; //the latest received value
- volatile unsigned int dmxcurrent = 0; //counter variable that is incremented every time we receive a value.
- volatile uint8_t dmxvalue[NUMBER_OF_CHANNELS];
- /* stores the DMX values we're interested in using--
- * keep in mind that this is 0-indexed. */
- volatile boolean dmxnewvalue = false;
- /* set to 1 when updated dmx values are received
- * (even if they are the same values as the last time). */
- SoftwareSerial mySerial = SoftwareSerial(3, 4);
- /******************************* Timer2 variable declarations *****************************/
- volatile uint8_t zerocounter = 0;
- /* a counter to hold the number of zeros received in sequence on the serial receive pin.
- * When we've received a minimum of 11 zeros in a row, we must be in a break. */
- void setup() {
- cli();
- #define WAIT_FOR_BREAK 7
- #define BREAK_DETECTED 6
- #define PACKET_RX_COMPLETE 5
- #define SETUP_FLAG 13
- #define LOOP 8
- #define WATCH 9
- pinMode(SETUP_FLAG,OUTPUT);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- pinMode(PACKET_RX_COMPLETE,OUTPUT);
- digitalWrite(PACKET_RX_COMPLETE,LOW);
- pinMode(BREAK_DETECTED,OUTPUT);
- digitalWrite(BREAK_DETECTED,LOW);
- pinMode(WAIT_FOR_BREAK,OUTPUT);
- digitalWrite(WAIT_FOR_BREAK,LOW);
- pinMode(LOOP,OUTPUT);
- digitalWrite(LOOP,LOW);
- pinMode(WATCH,OUTPUT);
- digitalWrite(WATCH,LOW);
- pinMode(RX_PIN, INPUT); //sets serial pin to receive data
- pinMode(RECEIVER_OUTPUT_ENABLE, OUTPUT);
- pinMode(DRIVER_OUTPUT_ENABLE, OUTPUT);
- digitalWrite(RECEIVER_OUTPUT_ENABLE, LOW);
- digitalWrite(DRIVER_OUTPUT_ENABLE, LOW); //sets pins 3 and 4 to low to enable reciever mode on the MAX485.
- /******************************* USART configuration ************************************/
- mySerial.begin(9600);
- mySerial.print("dmx_to_ws2801_bridge setup started. MCUSR = ");
- mySerial.print(MCUSR,HEX);
- MCUSR = (byte)0x00;
- mySerial.print("\n\r");
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- Serial.begin(250000);
- /* Each bit is 4uS long, hence 250Kbps baud rate */
- bitSet(UCSR0C, USBS0);
- // DMX-512 uses 2 stop bits
- bitClear(UCSR0B, RXCIE0); //disable USART reception interrupt
- //setupSPI();
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(PACKET_RX_COMPLETE,HIGH);
- digitalWrite(BREAK_DETECTED,HIGH);
- digitalWrite(WAIT_FOR_BREAK,HIGH);
- digitalWrite(LOOP,HIGH);
- sei();
- delay(1);
- digitalWrite(PACKET_RX_COMPLETE,LOW);
- digitalWrite(BREAK_DETECTED,LOW);
- digitalWrite(WAIT_FOR_BREAK,LOW);
- digitalWrite(LOOP,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- waitForBreak();
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,HIGH);
- digitalWrite(SETUP_FLAG,LOW);
- digitalWrite(SETUP_FLAG,LOW);
- } //end setup()
- void loop() {
- digitalWrite(8,HIGH); // the processor gets parked here while th0e ISRs are doing their thing.
- if (dmxnewvalue == 1) { //when a new set of values are received, jump to action loop...
- debug_action();
- dmxnewvalue = 0;
- dmxcurrent = -1; //DMX sends a start byte that we should ignore
- zerocounter = 0; //and then when finished reset variables and enable timer2 interrupt
- i = 0;
- //bitSet(TIMSK2, OCIE2A); //Enable Timer/Counter2 Output Compare Match A Interrupt
- digitalWrite(8,LOW);
- waitForBreak();
- }
- digitalWrite(8,LOW);
- } //end loop()
- //Timer2 compare match interrupt vector handler
- void waitForBreak()
- {
- while(1)
- {
- digitalWrite(WAIT_FOR_BREAK,HIGH);
- digitalWrite(WAIT_FOR_BREAK,HIGH);
- digitalWrite(WAIT_FOR_BREAK,LOW);
- while(bitRead(PIND, PIND0)); //Wait for RX to go LOW
- uint32_t uStart = micros();
- while(!bitRead(PIND,PIND0))
- {
- digitalWrite(WATCH,HIGH);
- digitalWrite(WATCH,HIGH);
- digitalWrite(WATCH,LOW);
- digitalWrite(WATCH,LOW);
- if(micros()-uStart >= DMX_BREAK_MICROS) //Break Detected, turn on Rx Interrupt
- {
- digitalWrite(BREAK_DETECTED,HIGH);
- digitalWrite(BREAK_DETECTED,HIGH);
- digitalWrite(BREAK_DETECTED,LOW);
- bitSet(UCSR0B, RXCIE0);
- return;
- }
- }
- }
- }
- ISR(USART_RX_vect){
- dmxreceived = UDR0;
- /* The receive buffer (UDR0) must be read during the reception ISR, or the ISR will just
- * execute again immediately upon exiting. */
- dmxcurrent++; //increment address counter
- if(dmxcurrent > dmxaddress) { //check if the current address is the one we want.
- dmxvalue[i] = dmxreceived;
- i++;
- if(i == NUMBER_OF_CHANNELS) {
- bitClear(UCSR0B, RXCIE0);
- digitalWrite(PACKET_RX_COMPLETE,HIGH);
- digitalWrite(PACKET_RX_COMPLETE,HIGH);
- dmxnewvalue = 1; //set newvalue, so that the main code can be executed.
- digitalWrite(PACKET_RX_COMPLETE,LOW);
- }
- }
- } // end ISR
- void action() {
- int i;
- byte r,b,g;
- for(i = 0; i< NUMBER_OF_CHANNELS; i+= 3)
- {
- r=dmxvalue[i];
- g=dmxvalue[i+1];
- b=dmxvalue[i+2];
- //we have ~360 RGB leds, to fit these into the 512 universe space, pair them in groups of three
- spi_out_three(r,g,b);
- spi_out_three(r,g,b);
- spi_out_three(r,g,b);
- }
- delayMicroseconds(500); //Triggers the end of a send session for the ws2801, causes new values to latch
- return; //go back to loop()
- } //end action() loop
- void debug_action(){
- mySerial.print("[");
- for(int i=0;i<NUMBER_OF_CHANNELS; i++)
- {
- mySerial.print((unsigned int)dmxvalue[i]);
- mySerial.print(", ");
- }
- mySerial.println("]\n\r");
- }
- /*
- // spi prescaler:
- // SPI2X SPR1 SPR0
- // 0 0 0 fosc/4
- // 0 0 1 fosc/16
- // 0 1 0 fosc/64
- // 0 1 1 fosc/MAXBRIGHT
- // 1 0 0 fosc/2
- // 1 0 1 fosc/8
- // 1 1 0 fosc/MAXBRIGHT
- // 1 1 1 fosc/64
- SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
- SPCR &= ~ ( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
- clr=SPSR; // clear SPI status reg
- clr=SPDR; // clear SPI data reg
- */
- void setupSPI(){
- byte clr;
- pinMode(10, OUTPUT);
- pinMode(11, OUTPUT);
- pinMode(13, OUTPUT);
- SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
- SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
- SPCR |= 1<<SPR0; // set prescaler bit SPR0
- clr=SPSR; // clear SPI status reg
- clr=SPDR; // clear SPI data reg
- //SPSR |= (1<<SPI2X); // set prescaler bits Commented to move to fosc/16
- SPSR &= ~(1<<SPI2X); // clear prescaler bits
- }
- inline void spi_out_three(byte b1, byte b2, byte b3)
- {
- SPDR = b1; // Start the transmission
- loop_until_bit_is_set(SPSR, SPIF);
- SPDR = b2; // Start the transmission
- loop_until_bit_is_set(SPSR, SPIF);
- SPDR = b3; // Start the transmission
- loop_until_bit_is_set(SPSR, SPIF);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement