#include "wiring_private.h"
//Area modulo UART software usw
#define USWRXB 32//define indica una macro (quando la chiamo mi da autmaticamente il valre 128 , come una costante).
#define USWTXB 32 // indice del trasmettitore seriale
#define USWBRT 26//Tau Baud Rate in Ticks (Usw Bit Rate)
volatile uint8_t uswidx,uswmask,uswtmp ,uswbyte[USWRXB];//index , mask, temporary buffer, recived vector,.
volatile uint8_t uswtmr,uswmasr,uswidr,uswfer[USWRXB/8+1];//index fer , mask fer, byte ferr vector.
volatile uint8_t uswidt,uswmast,uswtmt ,uswbytt[USWTXB],uswntx;//stesso significato delle variaibli di prima ma per la tramissione ,uswntx indica il num di byte che devo trasmettere(max indx)
void setup() {
Serial.begin(9600);
//inizilazzione Area UART:
uswidx=uswmask=uswtmp=uswidr=0;
uswmasr=1;
sbi(PCMSK2, PCINT18);//enable PCINT18 (IN PORTD) interrupt
sbi(PCICR,PCIE2); //enable PORTD PCINT interrupt.
OCR0A=0;//inizializzo il valore di ovf A =0.
TCCR0A &=~(_BV(WGM02)|_BV(WGM01)|_BV(WGM00)); //Normal Mode
sbi(TIMSK0,OCIE0A); //abilitiamo nel TMSKO la possibilità di generare un'interrupt dal valore COMPA
//Area di Stampa
Serial.print("Salve, mondo\n");
delay(1000);
Serial.println(F_CPU);
for(uint8_t i=0;i<uswidx;i++){
Serial.write(uswbyte[i]); //Serial.write converte ciò che c'è scritto in binario
uswbytt[i]=uswbyte[i];// passo i valori ricevuti in un buffer di tx
if(uswfer[uswidx>>3]&(1<< uswidx&7)) Serial.write('@');//controlla che il valore del bit nel byte ,sia 1 (frerror) o 0 (stop normale).
}
Serial.write(10); //Stampa un fine linea in codice ascii.
// Inizilizzazione modulo Trasmissione
sbi(DDRD,3);
sbi(PORTD , 3);// in questo modo metto il pin normalmente alto (riposo)
sbi(DDRD,4); // set 4D pin Output mode per testing
//sbi(TIMSK0,OCIE0B);
uswidt=0;
uswntx=uswidx;
uswmast=0xff; // come visto nell'ISR inizializzo il tutto con un bit di start
OCR0B=0;// in questo modo appena abilito il valore allora inizia subito con l'iinterrupt
sbi(TIMSK0 , OCIE0B); //Abilito la possibilità di sollevare un'interrupt con il valore OCIE0B.
delay(1000); //aspetto un secondo
while(Serial.available()) Serial.write(Serial.read()); //scrivi nel buffer il carattere che riceve
}
void loop() {
}
/*
//ISR NAKED:
ISR(TIMER0_COMPA_vect, ISR_NAKED){ //interrupt che si verifica ogni ovf. del timer0
sbi(PORTD,3);
asm("push r0 \n" "lds r0, 0x0081 \n" "pop r0 \n");// push r0 e pop r0
cbi(PORTD,3);
asm("reti \n");//assembly in line , reti = return from interrupt
}
*/
ISR(TIMER0_COMPA_vect){
uint8_t mask= uswmask;//uso una var. locale per ottimizzare una variabile globale
if(mask){ //if (boolean mask)
// sbi(PORTD,4); //lo uso per capire quando inzia
uint8_t tbit =PIND&0x04; //leggo il pin
OCR0A+= USWBRT;//imposto l'ocr0a a 1 tau
//Controllo Bit di Stop:
if(mask==0xff) {
if(tbit == 0) uswtmr |=uswmasr; // assegno 1 nella posizione della mask uswmasr(logica inversa 1 è ferror ,0 no).
uswmasr<<=1;
if(uswmasr==0){
if(uswidr< USWRXB/8+1) uswfer[uswidr++]=uswtmr;//se c'è spazio nei byte del vettore fer , allora salva il vettore degli errori
uswmasr=1;
uswtmr=0;
}
if(uswidx<USWRXB) uswidx++;
mask=0;
sbi(PCMSK2,PCINT18);//Riabilito l'interrupt
//FINE AREA BIT DI STOP
}else{
//Area Salvataggio dati in ARRAY
if(tbit) uswtmp |= mask; //Qui stiamo verificando che il valore tra la mschera e il buffer temproaneo , e lo scriviamo nel bit
mask<<=1; //shift a sx della mask
if(mask==0){ //fine lettura di un byte
if(uswidx<USWRXB) uswbyte[uswidx]=uswtmp; //salvo il valore del byte temporale nel vettore che può contenere al massimo 128 byte sse ho spazio in memoria
mask=0xff;//imposto il valore a 1 , in questo modo mi aspetto che ci sia il bit di stop
}
}
uswmask=mask; //riassegno il valore della var. locale a quella globale
// cbi(PORTD,4);// e quando finisce
}
}
ISR(TIMER0_COMPB_vect){
//uint8_t mask=uswmast; // Futura ottmizzazione
if(uswntx){
sbi(PORTD,4);//inzio controllo del tempo
//gestione bit di start
if(uswmast==0xff){
cbi(PORTD,3);
OCR0B=TCNT0+USWBRT;// qui serve a dire , da questo momento ogni volta che ti incrementerai il valore sarà corretto con il tempo reale
uswmast=1;
uswtmt=uswbytt[uswidt++];// prendo il prossimo byte.
uswntx--; //indica che il num di byte da trasmettere sta diminuendo.
}else{
if(uswmast){ // se la maschera è 1 allora inizia
if(uswtmt & uswmast)sbi(PORTD,3); else cbi(PORTD,3);//1 o 0
uswmast<<=1;
OCR0B+=USWBRT;//aspetta un tau (imposta 0CR0B A 1 tau)
}else{// se mask =0
sbi(PORTD,3);
OCR0B+=USWBRT;//aspetta un tau (imposta 0CR0B A 1 tau)
uswmast=0xff;//Assegno direttamente il valore "inizializza a bit di start", direttamente alla var. globaloe , tanto a che mi serve saper il valore della mask , se devo reinizializzarla?
}
cbi(PORTD,4);
}
}else cbi(TIMSK0 , OCIE0B); // quando non c'è nessun byte da tresmettere disabilito l'interrupt
}
ISR(PCINT2_vect){
if((PIND&0x04)==0){
OCR0A=TCNT0+USWBRT+USWBRT/2;//devo fare iniziare il contatore da valore attuale del timer + 3/2 tau
cbi(PCMSK2,PCINT18); //disabilito questo interrupt,infatti d'ora in avanti non mi serve leggere al cambio di valore nel pin , ma solo al tempo
uswmask=1;//quando verrà lanciato l'interrupt del timer , mettendo la mask a 1 inizierà la parte della mask
uswtmp=0;
}
}
//while(PIND&0x4);
//uint8_t pd=PORTD;
//uint8_t pd = PIND&0x4;