Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.70 KB | None | 0 0
  1. #include <SoftwareSerial.h>
  2.  
  3. /*
  4.  * dmx_ws2801_bridge.c
  5.  *
  6.  * Created: 6/18/2011 2:37:20 PM
  7.  *  Author: Administrator
  8.  */
  9.  
  10.  
  11. /******************************* Addressing variable declarations *****************************/
  12. //#include <avr/io.h>
  13.  
  14. //#include <WProgram.h>
  15. //#include <HardwareSerial.h>
  16.  
  17. #define NUMBER_OF_CHANNELS 12
  18. //the number of channels we want to receive (8 by default).
  19.  
  20.  
  21. //DMX Standard signifies a new transmition with a minimum ~88us LOW break period
  22. //followed by a minimum ~4us HIGH Mark After Break(MAB)
  23. #define DMX_BREAK_MICROS 80
  24. #define DMX_MAB_MICROS 4
  25.  
  26.  
  27.  
  28. void setupSPI();
  29. void spi_out_three(byte b1, byte b2, byte b3);
  30. void action();
  31.  
  32. uint16_t dmxaddress = 1;
  33.  
  34. /****************************** MAX485 variable declarations *****************************/
  35.  
  36. #define RECEIVER_OUTPUT_ENABLE 4
  37. /* receiver output enable (pin2) on the max485.  
  38.  *  will be left low to set the max485 to receive data. */
  39.  
  40. #define DRIVER_OUTPUT_ENABLE 5
  41. /* driver output enable (pin3) on the max485.  
  42.  *  will left low to disable driver output. */
  43.  
  44. #define RX_PIN 0   // serial receive pin, which takes the incoming data from the MAX485.
  45. #define TX_PIN 1   // serial transmission pin
  46.  
  47. /******************************* DMX variable declarations ********************************/
  48.  
  49. volatile uint16_t i = 0;              //dummy variable for dmxvalue[]
  50. volatile uint16_t j = 0;
  51. volatile uint8_t dmxreceived = 0;    //the latest received value
  52. volatile unsigned int dmxcurrent = 0;     //counter variable that is incremented every time we receive a value.
  53. volatile uint8_t dmxvalue[NUMBER_OF_CHANNELS];    
  54. /*  stores the DMX values we're interested in using--
  55.  *  keep in mind that this is 0-indexed. */
  56. volatile boolean dmxnewvalue = false;
  57. /*  set to 1 when updated dmx values are received
  58.  *  (even if they are the same values as the last time). */
  59.  
  60. SoftwareSerial mySerial =  SoftwareSerial(3, 4);
  61. /******************************* Timer2 variable declarations *****************************/
  62.  
  63. volatile uint8_t zerocounter = 0;          
  64. /* a counter to hold the number of zeros received in sequence on the serial receive pin.  
  65.  *  When we've received a minimum of 11 zeros in a row, we must be in a break.  */
  66.  
  67. void setup() {
  68.  
  69.  
  70.    cli();
  71.    
  72. #define WAIT_FOR_BREAK 7
  73. #define BREAK_DETECTED 6
  74. #define PACKET_RX_COMPLETE 5
  75. #define SETUP_FLAG 13
  76. #define LOOP 8
  77. #define WATCH 9
  78.  
  79.   pinMode(SETUP_FLAG,OUTPUT);
  80.   digitalWrite(SETUP_FLAG,HIGH);
  81.   digitalWrite(SETUP_FLAG,HIGH);
  82.   digitalWrite(SETUP_FLAG,LOW);
  83.   digitalWrite(SETUP_FLAG,LOW);
  84.   digitalWrite(SETUP_FLAG,HIGH);
  85.   digitalWrite(SETUP_FLAG,HIGH);
  86.   digitalWrite(SETUP_FLAG,LOW);
  87.   digitalWrite(SETUP_FLAG,LOW);
  88.   digitalWrite(SETUP_FLAG,HIGH);
  89.   digitalWrite(SETUP_FLAG,HIGH);
  90.   digitalWrite(SETUP_FLAG,LOW);
  91.   digitalWrite(SETUP_FLAG,LOW);
  92.   digitalWrite(SETUP_FLAG,HIGH);
  93.   digitalWrite(SETUP_FLAG,HIGH);
  94.   digitalWrite(SETUP_FLAG,LOW);
  95.   digitalWrite(SETUP_FLAG,LOW);
  96.   digitalWrite(SETUP_FLAG,HIGH);
  97.  
  98.  
  99.   pinMode(PACKET_RX_COMPLETE,OUTPUT);
  100.   digitalWrite(PACKET_RX_COMPLETE,LOW);
  101.  
  102.   pinMode(BREAK_DETECTED,OUTPUT);
  103.   digitalWrite(BREAK_DETECTED,LOW);
  104.  
  105.   pinMode(WAIT_FOR_BREAK,OUTPUT);
  106.   digitalWrite(WAIT_FOR_BREAK,LOW);
  107.  
  108.   pinMode(LOOP,OUTPUT);
  109.   digitalWrite(LOOP,LOW);
  110.  
  111.   pinMode(WATCH,OUTPUT);
  112.   digitalWrite(WATCH,LOW);
  113.  
  114.  
  115.   pinMode(RX_PIN, INPUT);  //sets serial pin to receive data
  116.  
  117.   pinMode(RECEIVER_OUTPUT_ENABLE, OUTPUT);
  118.   pinMode(DRIVER_OUTPUT_ENABLE, OUTPUT);
  119.   digitalWrite(RECEIVER_OUTPUT_ENABLE, LOW);
  120.   digitalWrite(DRIVER_OUTPUT_ENABLE, LOW);    //sets pins 3 and 4 to low to enable reciever mode on the MAX485.
  121.  
  122.  
  123.  
  124.  
  125.  
  126.   /******************************* USART configuration ************************************/
  127.   mySerial.begin(9600);
  128.   mySerial.print("dmx_to_ws2801_bridge setup started. MCUSR = ");
  129.   mySerial.print(MCUSR,HEX);
  130.   MCUSR = (byte)0x00;
  131.   mySerial.print("\n\r");
  132.   digitalWrite(SETUP_FLAG,LOW);
  133.   digitalWrite(SETUP_FLAG,LOW);
  134.   digitalWrite(SETUP_FLAG,HIGH);
  135.   digitalWrite(SETUP_FLAG,HIGH);
  136.   digitalWrite(SETUP_FLAG,LOW);
  137.   digitalWrite(SETUP_FLAG,LOW);
  138.   digitalWrite(SETUP_FLAG,HIGH);
  139.   digitalWrite(SETUP_FLAG,HIGH);
  140.  
  141.   Serial.begin(250000);
  142.   /* Each bit is 4uS long, hence 250Kbps baud rate */
  143.  
  144.   bitSet(UCSR0C, USBS0);
  145.   // DMX-512 uses 2 stop bits
  146.  
  147.   bitClear(UCSR0B, RXCIE0);  //disable USART reception interrupt    
  148.  
  149.   //setupSPI();
  150.  
  151.  
  152.   digitalWrite(SETUP_FLAG,HIGH);
  153.   digitalWrite(PACKET_RX_COMPLETE,HIGH);
  154.   digitalWrite(BREAK_DETECTED,HIGH);
  155.   digitalWrite(WAIT_FOR_BREAK,HIGH);
  156.   digitalWrite(LOOP,HIGH);
  157.  
  158.   sei();
  159.   delay(1);
  160.  
  161.  
  162.   digitalWrite(PACKET_RX_COMPLETE,LOW);
  163.   digitalWrite(BREAK_DETECTED,LOW);
  164.   digitalWrite(WAIT_FOR_BREAK,LOW);
  165.   digitalWrite(LOOP,LOW);
  166.   digitalWrite(SETUP_FLAG,LOW);
  167.  
  168.  
  169.  
  170.   digitalWrite(SETUP_FLAG,HIGH);
  171.   digitalWrite(SETUP_FLAG,HIGH);
  172.   digitalWrite(SETUP_FLAG,LOW);
  173.   digitalWrite(SETUP_FLAG,LOW);
  174.   digitalWrite(SETUP_FLAG,HIGH);
  175.   digitalWrite(SETUP_FLAG,HIGH);
  176.   digitalWrite(SETUP_FLAG,LOW);
  177.   digitalWrite(SETUP_FLAG,LOW);
  178.   digitalWrite(SETUP_FLAG,HIGH);
  179.   digitalWrite(SETUP_FLAG,HIGH);
  180.   digitalWrite(SETUP_FLAG,LOW);
  181.   digitalWrite(SETUP_FLAG,LOW);
  182.  
  183.   waitForBreak();
  184.  
  185.   digitalWrite(SETUP_FLAG,HIGH);
  186.   digitalWrite(SETUP_FLAG,HIGH);
  187.   digitalWrite(SETUP_FLAG,LOW);
  188.   digitalWrite(SETUP_FLAG,LOW);
  189.   digitalWrite(SETUP_FLAG,HIGH);
  190.   digitalWrite(SETUP_FLAG,HIGH);
  191.   digitalWrite(SETUP_FLAG,LOW);
  192.   digitalWrite(SETUP_FLAG,LOW);
  193.   digitalWrite(SETUP_FLAG,HIGH);
  194.   digitalWrite(SETUP_FLAG,HIGH);
  195.   digitalWrite(SETUP_FLAG,LOW);
  196.   digitalWrite(SETUP_FLAG,LOW);
  197. }  //end setup()
  198.  
  199.  
  200. void loop()  {
  201.   digitalWrite(8,HIGH); // the processor gets parked here while th0e ISRs are doing their thing.
  202.   if (dmxnewvalue == 1) {    //when a new set of values are received, jump to action loop...
  203.     debug_action();
  204.     dmxnewvalue = 0;
  205.     dmxcurrent = -1;      //DMX sends a start byte that we should ignore
  206.     zerocounter = 0;      //and then when finished reset variables and enable timer2 interrupt
  207.     i = 0;
  208.     //bitSet(TIMSK2, OCIE2A);    //Enable Timer/Counter2 Output Compare Match A Interrupt
  209.     digitalWrite(8,LOW);
  210.     waitForBreak();
  211.   }
  212.   digitalWrite(8,LOW);
  213. } //end loop()
  214.  
  215.  
  216.  
  217.  
  218.  
  219. //Timer2 compare match interrupt vector handler
  220. void waitForBreak()
  221. {
  222.   while(1)
  223.   {
  224.     digitalWrite(WAIT_FOR_BREAK,HIGH);
  225.     digitalWrite(WAIT_FOR_BREAK,HIGH);
  226.     digitalWrite(WAIT_FOR_BREAK,LOW);
  227.  
  228.     while(bitRead(PIND, PIND0)); //Wait for RX to go LOW
  229.  
  230.     uint32_t uStart = micros();
  231.  
  232.     while(!bitRead(PIND,PIND0))
  233.     {
  234.       digitalWrite(WATCH,HIGH);
  235.       digitalWrite(WATCH,HIGH);
  236.       digitalWrite(WATCH,LOW);
  237.       digitalWrite(WATCH,LOW);
  238.       if(micros()-uStart >= DMX_BREAK_MICROS) //Break Detected, turn on Rx Interrupt
  239.       {
  240.         digitalWrite(BREAK_DETECTED,HIGH);
  241.         digitalWrite(BREAK_DETECTED,HIGH);
  242.         digitalWrite(BREAK_DETECTED,LOW);
  243.         bitSet(UCSR0B, RXCIE0);
  244.         return;
  245.       }
  246.     }
  247.   }
  248. }
  249.  
  250.  
  251.  
  252.  
  253. ISR(USART_RX_vect){
  254.   dmxreceived = UDR0;
  255.   /* The receive buffer (UDR0) must be read during the reception ISR, or the ISR will just
  256.    *  execute again immediately upon exiting. */
  257.  
  258.   dmxcurrent++;                        //increment address counter
  259.  
  260.   if(dmxcurrent > dmxaddress) {         //check if the current address is the one we want.
  261.     dmxvalue[i] = dmxreceived;
  262.     i++;
  263.     if(i == NUMBER_OF_CHANNELS) {
  264.       bitClear(UCSR0B, RXCIE0);
  265.       digitalWrite(PACKET_RX_COMPLETE,HIGH);
  266.       digitalWrite(PACKET_RX_COMPLETE,HIGH);
  267.       dmxnewvalue = 1;                        //set newvalue, so that the main code can be executed.
  268.       digitalWrite(PACKET_RX_COMPLETE,LOW);
  269.     }
  270.   }
  271. } // end ISR
  272.  
  273.  
  274.  
  275. void action() {
  276.   int i;
  277.   byte  r,b,g;
  278.  
  279.  
  280.   for(i = 0; i< NUMBER_OF_CHANNELS; i+= 3)
  281.   {
  282.     r=dmxvalue[i];
  283.     g=dmxvalue[i+1];
  284.     b=dmxvalue[i+2];
  285.  
  286.     //we have ~360 RGB leds, to fit these into the 512 universe space, pair them in groups of three
  287.  
  288.     spi_out_three(r,g,b);
  289.     spi_out_three(r,g,b);
  290.     spi_out_three(r,g,b);
  291.   }
  292.   delayMicroseconds(500); //Triggers the end of a send session for the ws2801, causes new values to latch
  293.  
  294.   return;  //go back to loop()
  295. } //end action() loop
  296.  
  297. void debug_action(){
  298.  
  299.   mySerial.print("[");
  300.   for(int i=0;i<NUMBER_OF_CHANNELS; i++)
  301.   {
  302.     mySerial.print((unsigned int)dmxvalue[i]);
  303.     mySerial.print(", ");
  304.   }
  305.  
  306.   mySerial.println("]\n\r");
  307. }
  308.  
  309.  
  310. /*
  311.   // spi prescaler:
  312.  // SPI2X SPR1 SPR0
  313.  //   0     0     0    fosc/4
  314.  //   0     0     1    fosc/16
  315.  //   0     1     0    fosc/64
  316.  //   0     1     1    fosc/MAXBRIGHT
  317.  //   1     0     0    fosc/2
  318.  //   1     0     1    fosc/8
  319.  //   1     1     0    fosc/MAXBRIGHT
  320.  //   1     1     1    fosc/64
  321.  SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
  322.  SPCR &= ~ ( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
  323.  clr=SPSR; // clear SPI status reg
  324.  clr=SPDR; // clear SPI data reg
  325.  */
  326.  
  327. void setupSPI(){
  328.   byte clr;
  329.   pinMode(10, OUTPUT);
  330.   pinMode(11, OUTPUT);
  331.   pinMode(13, OUTPUT);
  332.   SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
  333.   SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
  334.   SPCR |= 1<<SPR0; // set prescaler bit SPR0
  335.  
  336.     clr=SPSR; // clear SPI status reg
  337.   clr=SPDR; // clear SPI data reg
  338.  
  339.   //SPSR |= (1<<SPI2X); // set prescaler bits  Commented to move to fosc/16
  340.   SPSR &= ~(1<<SPI2X); // clear prescaler bits
  341.  
  342. }
  343.  
  344. inline void spi_out_three(byte b1, byte b2, byte b3)
  345. {
  346.   SPDR = b1;              // Start the transmission
  347.   loop_until_bit_is_set(SPSR, SPIF);
  348.   SPDR = b2;              // Start the transmission
  349.   loop_until_bit_is_set(SPSR, SPIF);
  350.   SPDR = b3;              // Start the transmission
  351.   loop_until_bit_is_set(SPSR, SPIF);
  352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement