/*
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);
}
}