#include  "wiring_private.h"
// Area modulo UART SW usw
#define USWNRXB 32
// Tau Baud Rate in TICKS: 833 per 300, 26 per 9600
#define USWBRT 26
#define USWSTA 13
volatile uint8_t uswtmp, uswmask, uswidx, uswbyte[USWNRXB];
volatile uint8_t uswtmr, uswmasr, uswidr, uswfer[USWNRXB/8+1];
volatile uint8_t uswtmt, uswmast, uswidt, uswntx, uswtxb, uswbytt[USWNRXB/8+1];

void setup() {
  Serial.begin(9600);
// Inizializzazione Area UART
  uswidx = uswmask = uswtmp = 0;
  sbi(PCMSK2, PCINT18);
  sbi(PCICR, PCIE2);
  OCR0A = 0;
  // cbi(TCCR0A, WGM00); // Normal Mode
  // cbi(TCCR0A, WGM01); // Normal Mode
  // cbi(TCCR0A, WGM02); // Normal Mode
  // ~ <- (Alt + 126)
  TCCR0A &=~(_BV(WGM02) | _BV(WGM01) | _BV(WGM00)); // Normal Mode
  sbi(TIMSK0, OCIE0A);
  // Output D3 per testing
  sbi(DDRD, 3);

  Serial.print("Salve, mondo\n");
  delay(1000);
  Serial.println(F_CPU);
  for(uint8_t i = 0; i < uswidx; i++) {
    Serial.write(uswbyte[i]);
    if(uswfer[i] == 0) Serial.write('@');
  }
  Serial.write(10);
  // Inizzializzazione modulo TX  
  sbi(DDRD, 3); // Normalmente TX
  sbi(PORTD, 3); // Normalmente alto
  OCR0B = 0;
  uswtmt = 0;
  uswmast = 0xff;
  uswntx = uswidx;
  OCR0B = TCNT0 + 1;
  sbi(TIMSK0, OCIE0B);
}

void loop() { 
}

ISR(TIMER0_COMPB_vect) {
  if(uswntx) {
    sbi(PORTD, 4);
    if(uswmast) {
      if(uswmast == 0xff) {
        cbi(PORTD, 3); // Start bit
        OCR0B = TCNT0 + USWBRT;
        uswmast = 1;
        uswtmt = uswbytt[uswidt++];
      }
      else {}
      if(uswtmt & uswmast) sbi(PORTD, 3);
      else cbi(PORTD,3);
      uswmask <<= 1;
      OCR0B += USWBRT;
    }
    else {
      sbi(PORTD, 3); // Stop bit
      OCR0B += USWBRT;
      uswntx--;
      uswidt--;
      uswmast = 0xff;
    }
    cbi(PORTD, 4);
  } else cbi(TIMSK0, OCIE0B);
}

ISR(TIMER0_COMPA_vect) {
// ISR(TIMER0_COMPA_vect, ISR_NAKED) {}
  uint8_t mask = uswmask;
  if(mask) {
    sbi(PORTD, 3);
    cbi(PORTD, 3);
    asm("reti \n");

    uint8_t tbit = PIND & 0x04; //
    OCR0A += USWBRT;
    if(mask == 0xff) {
      uint8_t ie = uswidx >> 3;
      uint8_t ie1 = uswidx &7;
      if(ie1 == 0) uswfer[ie] = 0;
      if(tbit == 0) uswfer[ie] |= (1 << ie1);

      if(uswidx < USWNRXB) uswidx++;
    }
    else {
    if(tbit) uswtmp |= uswmask;
    uswmasr <<= 1; 
      if(uswmasr == 0) {
        if(uswidr < USWNRXB/8+1) uswbyte[uswidx] = uswtmp;
        uswmasr = 0xff;
        // sbi(PCMSK2, PCINT18); // Riattiva interrupt su PC
      }
    }
    uswmask = mask;
    cbi(PORTD, 3);
  };
}

ISR(PCINT2_vect){
  if((PIND & 4) == 0) {
  OCR0A = TCNT0 + USWBRT + USWSTA;
  cbi(PCMSK2, PCINT18);
  uswmask = 1;
  uswtmp = 0;
  }
}
D0D1D2D3D4D5D6D7GNDLOGIC