/*
15/5/2001  IK1PXM - Programma Beacon BPSK31; inviato a RKe.
Trasmette un testo ASCII e il numero dei messaggi trasmessi.
Le parti del programma commentate appartengonono a versioni precedenti del programma.
Il programma è distribuito nello stato in cui si trova, non si assumono responsabilità sul funzionamento.
*/
long memtempo;
#define SLAVESELECT 10//ss
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck

char vet_CARASCT[]={"bbr BEACON IK1PXM/B        ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 ., b"}; 

byte cnt = 0;
byte cnt_t = 0; // contatore transizione bit
byte cntb = 0; //contatore n.bit solo per prova
//byte vetalfa[9]={200,197,189,167,127, 72, 28,  6,  0};
byte vetalfa[8]={200,197,189,167, 72, 28,  6,  0}; //tolto il 127 zero volt
byte vetalfa16[17]={201,200,198,194,188,180,168,150,127,100, 71,47, 28,15,  6, 2, 0};
//byte vetalfa32[33]={200,200,200,199,198,196,194,191,188,184,180,174,168,160,150,140,127,114,100, 85, 71, 59, 47, 37, 28, 21, 15, 10, 6, 4, 2, 0, 0};
byte vetbitpsk[40]={0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,1,0,0,1,0,0}; // corrisponde a: "ciao "
// serve se  si invertono i pin potenziometro int vetalfa[10]=  { 55, 58, 66, 88,128,183,227,249,255}; 
boolean invers = true;
boolean PSKON = true;
boolean UD=true;
//boolean UDP=false;
int nel_vetbitpsk;
int CNTPSKOFF, CNTPSKON;
int WPSK, L_WPSK,st_bpsk,CNT_L_WPSK;
int C_VAR,L_VAR;
int cntmsg=9997;
void setup()
{  

nel_vetbitpsk = sizeof(vetbitpsk)-1;
//Serial.begin(19200);
inipot();  //inizializza potenziometro
 
}

void loop()
{ 
if ((millis() - memtempo) >= 2 )
 { memtempo = millis();
      beaconpsk31();
  }    
}

void beaconpsk31() //beacon BPSK31 viene eseguito ogni 2 ms
{

 if (PSKON == true) 
 { 
    if (invers == true) {if(cnt_t < 16){cnt_t++;}}  else {if(cnt_t > 0){cnt_t--;}};
  //if (invers == true) {if(cnt_t < 32){cnt_t++;}}  else {if(cnt_t > 0){cnt_t--;}};
  //if (invers == true) {cnt_t=16;}  else {cnt_t=0;}; //commutazione a gradino !!!
 }
  else // se false uscita a zero cnt_t = valore intermedio
 {//cnt_t=8; //interruzione "brusca"
  if (invers == true) {if(cnt_t < 8){cnt_t++;}}  else {if(cnt_t > 8){cnt_t--;}}; //interuzione "morbida"
 } 
 
 write_pot(vetalfa16[cnt_t]);

cnt++; if (cnt>=16) //era 8
{ cnt =0; //periodicità elaborazione bit 32 ms



  switch(st_bpsk)
      {
        case 0 : //
        if(CNT_L_WPSK < L_WPSK)
        {
        if((WPSK &1)== 1){UD=true;}else{UD=false;}
        WPSK=WPSK/2; //dimezza per esaminare poi il bit successivo
        CNT_L_WPSK++;
        }
        else
        {UD=false;//fine parola, trasmetti il primo bit0 di separazione parola
        st_bpsk = 2;} //
        ;break;
                
        case 1 : // trasmetti il primo bit0 di separazione parola
        UD= false; st_bpsk = 2;
        ;break;

        case 2 : //trasmetti il secondo bit0 di separazione parola e recupera la parola successiva
        UD= false;
        //ASCIIVARICODE( vet_CARASCT[13], &WPSK, &L_WPSK);
        ASCIIVARICODE( vet_CARASCT[cntb]);
        cntb++; if (cntb> (sizeof(vet_CARASCT) -1))
       {cntb=0;PSKON=false;CNTPSKOFF = 0;
        cntmsg++; if (cntmsg >9999){cntmsg=0;};intasc(cntmsg,& vet_CARASCT[20],4,0);    // aggiorna e prepara numero messaggio trasmesso
       } //arrivato in fondo spegne e attende un poco
        WPSK=C_VAR;L_WPSK=L_VAR;
        CNT_L_WPSK=0;
        st_bpsk = 0;
        ;break;
      }

//cntb++; if (cntb > nel_vetbitpsk){cntb=0;}; if (vetbitpsk[cntb]==1){UD=true;}else{UD=false;} // beacon rudimentale, trasmetti un pattern di bit 

if (UD== false) {if (invers== true){invers=false;}else{invers=true;}} //se il bit è zero inverti fase, altrimenti fai nullla

if (PSKON != true){ CNTPSKOFF++; cntb=0; if( CNTPSKOFF > 200) {CNTPSKON = 0;PSKON = true;}} //se in OFF  blocca contatore caratteri e conta l'attesa prima di ripartire

}

}


//funzione converte un carattere ASCII nel corrispondente codice Varicode e lunghezza
void ASCIIVARICODE( char C )

{
if (C >= 65 && C <= 90)
{ //sono lettere
 if (C == 'A'){C_VAR= B1101;L_VAR = 4;} //il lsb è il primo a essere trasmesso
 if (C == 'B'){C_VAR= B1111101;L_VAR = 7;}
 if (C == 'C'){C_VAR= B111101;L_VAR = 6;}
 if (C == 'D'){C_VAR= B101101;L_VAR = 6;}
 if (C == 'E'){C_VAR= B00011;L_VAR = 2;}
 if (C == 'F'){C_VAR= B101111;L_VAR = 6;}
 if (C == 'G'){C_VAR= B1101101;L_VAR = 7;}
 if (C == 'H'){C_VAR= B110101;L_VAR = 6;}
 if (C == 'I'){C_VAR= B1011;L_VAR = 4;}
 if (C == 'J'){C_VAR= 431 ;L_VAR = 9;} //B110101111
 if (C == 'K'){C_VAR= B11111101;L_VAR = 8;}
 if (C == 'L'){C_VAR= B11011;L_VAR = 5;}
 if (C == 'M'){C_VAR= B110111;L_VAR = 6;}
 if (C == 'N'){C_VAR= B01111;L_VAR = 4;}
 if (C == 'O'){C_VAR= B111;L_VAR = 3;}
 if (C == 'P'){C_VAR= B111111;L_VAR = 6;}
 if (C == 'Q'){C_VAR= 507 ;L_VAR = 9;} //B111111011
 if (C == 'R'){C_VAR= B10101;L_VAR = 5;}
 if (C == 'S'){C_VAR= B11101;L_VAR = 5;}
 if (C == 'T'){C_VAR= B101;L_VAR = 3;}
 if (C == 'U'){C_VAR= B111011;L_VAR = 6;}
 if (C == 'V'){C_VAR= B1101111;L_VAR = 7;}
 if (C == 'W'){C_VAR= B1101011;L_VAR = 7;}
 if (C == 'X'){C_VAR= B11111011;L_VAR = 8;}
 if (C == 'Y'){C_VAR= B1011101;L_VAR = 7;}
 if (C == 'Z'){C_VAR= 343 ;L_VAR = 9;} //B101010111
}
else
{//sono cifre 
 if (C == '-'){C_VAR= B00011;L_VAR = 0;}
 if (C == '?'){C_VAR= B11001;L_VAR = 0;}
 if (C == ':'){C_VAR= B01110;L_VAR = 0;}
 if (C == '$'){C_VAR= B01001;L_VAR = 0;}
 if (C == '3'){C_VAR= B11111111;L_VAR = 8;}
 if (C == '!'){C_VAR= B01101;L_VAR = 0;}
 if (C == '&'){C_VAR= B11010;L_VAR = 0;}
 if (C == '#'){C_VAR= B10100;L_VAR = 0;}
 if (C == '8'){C_VAR= 427;L_VAR = 9;}
 if (C == '£'){C_VAR= B01011;L_VAR = 0;}
 if (C == '('){C_VAR= B01111;L_VAR = 0;}
 if (C == ')'){C_VAR= B10010;L_VAR = 0;}
 if (C == '.'){C_VAR= B1110101;L_VAR = 7;}
 if (C == ','){C_VAR= B1010111;L_VAR = 7;}
 if (C == '9'){C_VAR= 475;L_VAR = 9;}
 if (C == '0'){C_VAR= B11101101;L_VAR = 8;}
 if (C == '1'){C_VAR= B10111101;L_VAR = 8;}
 if (C == '4'){C_VAR= 477 ;L_VAR = 9;} //B111011101
 if (C == '^'){C_VAR= B00101;L_VAR = 0;}
 if (C == '5'){C_VAR= 437;L_VAR = 9;}
 if (C == '7'){C_VAR= 363;L_VAR = 9;}
 if (C == '='){C_VAR= B11110;L_VAR = 0;}
 if (C == '2'){C_VAR= B10110111;L_VAR = 8;}
 if (C == '/'){C_VAR= 491;L_VAR = 9;}
 if (C == '6'){C_VAR= 429;L_VAR = 9;}
 if (C == '+'){C_VAR= B10001;L_VAR = 0;}

//if (C == 'l'){C_VAR= B11111;L_VAR = 0;} //passa a L_VAR
//if (C == 'c'){C_VAR= B11011;L_VAR = 0;} //passa a cifre
if (C == ' '){C_VAR= B00001;L_VAR = 1;} //spazio
if (C == 'f'){C_VAR= B10111;L_VAR = 5;} //line feed
if (C == 'r'){C_VAR= B11111;L_VAR = 5;} //carriage return
if (C == 'b'){C_VAR= B0;L_VAR = 14;} // blank carattere nullo tutti zeri per sincronismo

}
}


void inipot()  //inizializza SPI del potenziometro
{ //setup potenziometro
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT); // non serve
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR; clr=SPDR; 
  delay(10);
} 

char spi_transfer(volatile char data)
{ SPDR = data;                     // Start the transmission
  while (!(SPSR & (1<<SPIF))){ };  // Wait the end of the transmission 
  return SPDR;                    // return the received byte
}

byte write_pot(int value) // per il pot digitale  MCP41010 
{ digitalWrite(SLAVESELECT,LOW); spi_transfer(B00010001); spi_transfer(value); //2 byte di codice di comando
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

//funzione converte un numero intero max 9999 nei 4 caratteri ascii corrispondenti e posiziona punto
// il risultato avviene  trasmesso tramite puntatore   31/5/09
void intasc(int num, char *na, int nc,int np)
{
  # define sepdec  46  // 44 virgola;  46 punto
 // variabili locali usate dalla funzione:
 // nc numero cifre da 3 a 4; np posizione virgola da 0 a 3 prima della ultima cifra
 boolean cifrasignif = false;
 boolean cifredecim = false; // se true ora sono cifre decimali in cui lo zero va sempre scritto
 int nummigl; int numcent; int numdeci; int numunit; int nummiglper1000; int numcentper100; int numero;
numero = num; // il dato in ingresso non viene modificato
 if (nc > 4) { nc = 4;}; if (nc < 3) { nc = 3;}
 if (np > 3) { np = 3;}; if (np < 0) { np = 0;}

 if (numero > 9999) { numero = 9999;}
 if (numero < 0) { numero = 0;}
int ic = 0 ; //indice cifra  
cifrasignif = false;
nummigl = numero/1000;nummiglper1000 = nummigl*1000;

if (nc == 4)  //scrivi la quarta cifra solo se richiesto
{
if (nummigl == 0) { na[ic]=32;ic++;} // forza il carattere spazio ( 32 in ASCII)
else
{ na[ic]=nummigl + 48; ic++; //carica la cifra da 0 a 9 in ASCII
cifrasignif = true;//la cifra ï¿½ significativa
}
}
if (np == 3) { na[ic]= sepdec ;cifredecim = true; ic++;}  // inserisci simbolo inizio decimali
numcent = (numero-nummiglper1000)/100; numcentper100 = numcent*100;
if (numcent == 0)
//{     if (cifrasignif == false) { na[ic]=32;ic++;} else { na[ic]=48;ic++; } }
{     if ((cifrasignif == true)||(cifredecim == true))  { na[ic]=48;} else { na[ic]=32;}ic++; }


else
{  na[ic] = numcent + 48; ic++; cifrasignif = true;}

if (np == 2) { na[ic]= sepdec ; cifredecim = true; ic++;} 
numdeci = (numero-nummiglper1000-numcentper100)/10;
if (numdeci == 0)
//{     if (cifrasignif == false) {  na[ic]=32; ic++; } else { na[ic]=48;ic++; } }
{     if ((cifrasignif == true)||(cifredecim == true))  { na[ic]=48;} else { na[ic]=32;}ic++; }

else
{  na[ic] = numdeci + 48;ic++;} 
if (np == 1) { na[ic]= sepdec ;cifredecim = true; ic++;} 
//la cifra delle unitï¿½ viene sempre scritta
numunit = (numero-nummiglper1000-numcentper100-numdeci*10); na[ic] = numunit + 48;
}

