/* Copyright (C) Arnaud Houdelette 2012-2014 Copyright (C) Emmanuel Langlois 2012-2014 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // definition des fonction cbi sbi idem assembleur #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // déclaration des tableaux de données byte tab_input_pc[1026]; // venant du pc byte tab_input_dmx[534]; // données venant de l'extérieur : les 512 premiers DMX; les 20 suivant 4x8 bp + 16 analogique 8bits ; 1 octet d'etat // reception volatile int index_input_pc=0; // entrée serial 0 volatile int index_output_pc=0; // sortie serial 0 volatile int index_input_dmx=513; // entrée dmx volatile int index_output_dmx=0; //sortie dmx -2 en attente de fin de transmission; -1 break; 0 à 512 transmission volatile int index_output_dmx2=0; //sortie dmx -2 en attente de fin de transmission; -1 break; 0 à 512 transmission volatile int etat_input_pc=0; // 0 raz ; 1 esc reçu ; 2 D reçu : pret à recevoir ; 3 prèt à emmetre volatile int start_code_rec=-1; char key; // caractère reçu serial 0 int cpt_ana = 0; int ledPin = 13; // led interne int tx1pin = 18; // pin DMX serial 1 int tx2pin = 16; // pin DMX serial 2 byte brk_timer_start=181; // def : 150us byte mab_timer_start=231; //def : 50us int nb_circuits=512; int flag_merge1=1; int flag_merge2=1; // vecteur d'inéruption pour reception pc ISR(USART0_RX_vect) { char c,r; byte *pb, *pe; r = UCSR0A; c = UDR0; switch (etat_input_pc) { case 0: // on attend un 'esc' pour commencer if (c==27) { etat_input_pc=1; digitalWrite(ledPin, LOW);break;} break; case 1: // on attend 'D' pour recevoir if (c==68) { etat_input_pc=2; index_input_pc=1; tab_input_dmx[533]=68; index_output_pc=1; // on init l'index d'emmission vers le pc ( le 0 n'est pas emit => start code) sbi(UCSR0B, UDRIE0); // activation de l'intéruption registre emmission } // Esc 'C' réinit if (c==67) { etat_input_pc=0; pe=tab_input_pc+1026; for(pb=tab_input_pc;pb 1024) {// on se prépare à emmetre vers le pc etat_input_pc=0; digitalWrite(ledPin, HIGH); } break; case 10: // 1er parametre : nb de circuits / 2 - 1 ( de 2 a 512 ) etat_input_pc++; //nb_circuits= ((int)c)*2 + 2; break; case 11: // 2nd parametre : duree du break en us etat_input_pc++; //brk_timer_start = 255 - (c/2) +1; break; case 12: // 3eme parametre : duree du mab en us etat_input_pc++; //mab_timer_start = 255 - (c/2) +1; break; case 13: // 4eme parametre : merge etat_input_pc=0; flag_merge1 = c & 1; flag_merge2 = c/2 & 1; // on a tout recu, on reponds tab_input_dmx[533]=66; index_output_pc=533; // on init l'index d'emmission vers le pc ( uniquement etat : 66 'B' ) sbi(UCSR0B, UDRIE0); break; default: // on fait rien break; } } // vecteur d'intéruption pour reception dmx ISR(USART1_RX_vect) { char c,r; r = UCSR1A; c = UDR1; if (r & (1< break if(index_output_dmx==-4) index_output_dmx=-1; } // vecteur : USART 1 transmission registre vide ISR(USART1_UDRE_vect) { if (index_output_dmx>=0) { //si index >=0 caratère suivant if (flag_merge1==1) {UDR1 = max(tab_input_pc[index_output_dmx],tab_input_dmx[index_output_dmx]);} else {UDR1 = tab_input_pc[index_output_dmx];} index_output_dmx++; } // si 512 transmits => mise en attente de fin de transmission // desactivation de l'intéruption sur le registre if (index_output_dmx>nb_circuits) {index_output_dmx=-4;cbi(UCSR1B, UDRIE1);} } // vecteur d'intéruption pour transmission DMX sur serial 2 // vecteur : USART 1 transmission buffer vide ISR(USART2_TX_vect) { // si l'USART 2 est vide => break if(index_output_dmx2==-4) index_output_dmx2=-1; } // vecteur : USART 2 transmission registre vide ISR(USART2_UDRE_vect) { if (index_output_dmx2>=0) { //si index >=0 caratère suivant if (flag_merge2==1) {UDR2 = max(tab_input_pc[index_output_dmx2+512],tab_input_dmx[index_output_dmx2]);} else {UDR2 = tab_input_pc[index_output_dmx2+512];} index_output_dmx2++; } // si 512 transmits => mise en attente de fin de transmission // desactivation de l'intéruption sur le registre if (index_output_dmx2>nb_circuits) {index_output_dmx2=-4;cbi(UCSR2B, UDRIE2);} } // vecteur d'intéruption pour transmission vers le pc sur serial 0 // vecteur registre de transmission ISR(USART0_UDRE_vect) { //caratère suivant UDR0 = tab_input_dmx[index_output_pc]; index_output_pc++; if (index_output_pc>532) { cbi(UCSR0B, UDRIE0); } } ISR(TIMER2_OVF_vect) { if (index_output_dmx==-2 ) { digitalWrite(tx1pin, HIGH); // on met la broche 18 à 1 pendant 10 µs digitalWrite(tx2pin, HIGH); // on met la broche 16 à 1 pendant 10 µs //digitalWrite(ledPin, HIGH); index_output_dmx=-3; index_output_dmx2=-3; TCNT2 = mab_timer_start ;// RAZ compteur timer TIFR2 = 0 ; //Clear Flags timer return; } if (index_output_dmx==-3 ) { sbi(UCSR1B, TXEN1); // on redémarre la transmission index_output_dmx=0; // on se prépare à émmettre à partir du stat code ( 513 octets ) sbi(UCSR1B, UDRIE1); // on réactive l'intéruption du registre sbi(UCSR2B, TXEN2); // on redémarre la transmission index_output_dmx2=0; // on se prépare à émmettre à partir du stat code ( 513 octets ) sbi(UCSR2B, UDRIE2); // on réactive l'intéruption du registre TIMSK2 = 0 ; //desactivation intéruption A &B TCCR2B = 0; } } void setup() { // initialisation du stat code à 0 tab_input_pc[0]=0; // initialisation de la liaison série pc à 0,5MB/s //Serial.begin(460800); UCSR0A = 1 << U2X0; UBRR0H=0; UBRR0L = 3; UCSR0C = 6; // initialisation à 250k de serial 1 // baudrate UCSR1A = 1 << U2X1; UBRR1H=0; UBRR1L = 7; // 2 bit de stop; pas de parité; 8 bits de données UCSR1C = 14; // initialisation à 250k de serial 2 // baudrate UCSR2A = 1 << U2X2; UBRR2H=0; UBRR2L = 7; // 2 bit de stop; pas de parité; 8 bits de données UCSR2C = 14; // activation transmission et intéruption serial 1 sbi(UCSR1B, RXEN1); //Reception sbi(UCSR1B, TXEN1); //Transmission sbi(UCSR1B, RXCIE1); //Interruption sur reception sbi(UCSR1B, TXCIE1); //Interruption pour fin de transmission // activation transmission et intéruption serial 2 sbi(UCSR2B, TXEN2); //Transmission sbi(UCSR2B, TXCIE2); //Interruption pour fin de transmission sbi(UCSR0B, RXEN0); //Reception sbi(UCSR0B, RXCIE0); //Interruption sur reception sbi(UCSR0B, TXEN0); //Transmission // Init convertion analogique pour le premier canal pin0 ADCSRB = (ADCSRB & ~(1 << MUX5)); ADMUX = 96; //01100000 reférence sur le 5v et alignement pour lecture sur 8 bits sbi(ADCSRA, ADSC); // init timer break TIMSK2 = 0; TCCR2B = 0; TCCR2A = 0; // 00000000 ASSR &= ~(1< 2µs } // fin du break // suite du code tab_input_dmx[513]= PINA; tab_input_dmx[514]= PINC; tab_input_dmx[515]=0; tab_input_dmx[516]=0; if ( ! bit_is_set(ADCSRA, ADSC)) { //digitalWrite(ledPin, HIGH); tab_input_dmx[517+cpt_ana++]=ADCH; if (cpt_ana>15) cpt_ana=0; ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((cpt_ana >> 3) & 0x01) << MUX5); ADMUX = 96 | (cpt_ana & 0x07); sbi(ADCSRA, ADSC); } }