#include #include "USBDesc.h" #include "Platform.h" #include int main(void) { init(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); } return 0; } // 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[514]; // venant du pc byte tab_input_dmx[518]; // données venant de l'extérieur : les 512 premiers DMX; les 4 suivant 4x8 bp ; // 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 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; int ledPin = 13; // led interne int tx1pin = 1; // pin DMX serial 1 byte brk_timer_end=75; // def : 150us byte mab_timer_end=25; //def : 50us int nb_circuits=512; int flag_merge1=1; volatile int emissionPc=0; // Fonctions void litUSB(char c); void ecritUSB(); void CDC_accept(); /* ------------ Gestion Liaison USB -------------- */ /* On a surcharge tout ca pour optimiser les temps de transfert */ // lancé par interruption USB sur reception d'un char <- Cette fonction nécessite une modif de la lib arduino // l'interet est de ne pas utiliser le buffer de la classe Serial, trop petit (64o) void CDC_accept() { int c = USB_Recv(CDC_RX); litUSB(c); } /* ------------ Fin Gestion Liaison USB -------------- */ // lecture d'un caractere sur USB void litUSB(char c) { //char c; byte *pb, *pe; switch (etat_input_pc) { case 0: // on attend un 'esc' pour commencer if (c==27) { etat_input_pc=1; break;} break; case 1: // on attend 'D' pour recevoir if (c==68) { etat_input_pc=2; index_input_pc=1; tab_input_dmx[517]=68; index_output_pc=1; // on init l'index d'emmission vers le pc ( le 0 n'est pas emit => start code) emissionPc=1; // activation de l'intéruption registre emmission } // Esc 'C' réinit if (c==67) { etat_input_pc=0; pe=tab_input_pc+514; for(pb=tab_input_pc;pb 512) {// 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_end = (c/2); break; case 12: // 3eme parametre : duree du mab en us etat_input_pc++; mab_timer_end = (c/2); break; case 13: // 4eme parametre : merge etat_input_pc=0; flag_merge1 = c & 1; // on a tout recu, on reponds tab_input_dmx[517]=66; index_output_pc=517; // on init l'index d'emmission vers le pc ( uniquement etat : 66 'B' ) emissionPc=1; break; default: // on fait rien break; } } void ecritUSB() { if(index_output_pc > 516){ USB_Send(CDC_TX,tab_input_dmx+index_output_pc,1); emissionPc=0; return; } index_output_pc+= USB_Send(CDC_TX,tab_input_dmx+index_output_pc, 517-index_output_pc); if (index_output_pc>516) { emissionPc=0; } } // 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);} } ISR(TIMER4_COMPA_vect) { if (index_output_dmx==-2 ) { digitalWrite(tx1pin, HIGH); // on met la broche 18 à 1 pendant 10 µs index_output_dmx=-3; OCR4A = mab_timer_end ; TCNT4 = 0 ;// RAZ compteur timer TIFR4 = 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 //digitalWrite(ledPin, HIGH); TIMSK4= 0 ; //desactivation intéruption A &B TCCR4B = 0; } } void setup() { // initialisation du stat code à 0 etat_input_pc=0; tab_input_pc[0]=0; // init pin led interne en sortie pinMode(ledPin, OUTPUT); // 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; // 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 // init timer break TIMSK4 = 0; TCCR4C = 0; TCCR4B = 0; TCCR4A = 0; // 00000000 TCNT4 = 0; // compteur TC4H=0; sei(); // préparation du premier break index_output_dmx=-1; } void loop() { // génération du break en tache principale int cpt = 0; if (index_output_dmx==-1 ) { index_output_dmx=-2; pinMode(tx1pin, OUTPUT); // on met la broche 18 en mode sortie cbi(UCSR1B, TXEN1); //on stop la transmission digitalWrite(tx1pin, LOW); // on met la broche 18 à 0 OCR4A = brk_timer_end ; // val 120 µs TCNT4 = 0 ;// RAZ compteur timer TIFR4 = 0 ; //Clear Flags timer TIMSK4 = 64 ; //activation intéruption A &B TCCR4B = 6; // 00000011 division par 32 de l'horloge base => 2µs } // fin du break // octets d'état. Pour le moment, tous à 0 tab_input_dmx[513]= 0; tab_input_dmx[514]= 0; tab_input_dmx[515]=0; tab_input_dmx[516]=0; if(_usbLineInfo.lineState) { // Si port serie USB ouvert if(emissionPc!=0) { ecritUSB(); } } else { // Si port fermé : on eteint la LED digitalWrite(ledPin, LOW); // et on réinitialise l'état d'entrée USB etat_input_pc=0; } }