#include "wiring_private.h"
// Area modulo UART SW usw
#define USWNRXB 32
#define USWNTXB 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, uswbytt[USWNTXB];
//
void setup() {
Serial.begin(9600);
// Inizializzazione Area UART usw
uswidx=uswmask=uswtmp=uswidr = 0;
uswmasr=1;
sbi(PCMSK2, PCINT18);
sbi(PCICR,PCIE2);
OCR0A=0;
cbi(TCCR0A, WGM00); // Normal Mode
cbi(TCCR0A, WGM01); // Normal Mode
cbi(TCCR0B, WGM02); // Normal Mode
sbi(TIMSK0, OCIE0A);
// Output D4 per testing
sbi(DDRD, 4);
//
Serial.print("Salve, mondo\n");
delay(1000);
Serial.println(F_CPU);
for(uint8_t i=0; i<uswidx; i++){
Serial.write(uswbyte[i]);
uswbytt[i] = uswbyte[i]+1;
if(uswfer[uswidx >>3] & (1 << uswidx&7))Serial.write('@');
}
Serial.write(10);
// Inizializzatione modulo TX
sbi(DDRD, 3); // Tx Pin
sbi(PORTD, 3); // Normalmente H
uswidt = 0;
uswmast=0xff;
uswntx = uswidx;
OCR0B=TCNT0+USWBRT;
cbi(TIFR0,OCF0B);
sbi(TIMSK0, OCIE0B);
delay(1000);
while(Serial.available())Serial.write(Serial.read());
}
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);
uswmast <<=1;
OCR0B +=USWBRT;
}
} else {
sbi(PORTD,3); // Stop bit
OCR0B +=USWBRT;
uswntx--; uswidt++;
uswmast=0xff;
}
cbi(PORTD,4);
} else cbi(TIMSK0, OCIE0B); // Disable Interrupt
}
ISR(TIMER0_COMPA_vect){
//ISR(TIMER0_COMPA_vect, ISR_NAKED){
uint8_t mask = uswmask;
if(mask){
//sbi(PORTD,4);
uint8_t tbit = PIND & 0x04; //
OCR0A +=USWBRT;
if(mask == 0xff){ // uswfer[uswidx >>3] |= 1 << uswidx&7
if(tbit == 0) uswtmr |= uswmasr;
uswmasr <<=1;
if(uswmasr == 0) {
if(uswidr < USWNRXB/8+1) uswfer[uswidr++] = uswtmr;
uswmasr=1;
uswtmr=0;
}
if(uswidx < USWNRXB) uswidx++;
mask=0;
sbi(PCMSK2, PCINT18); // Riattiva interrupt su PC
} else {
if(tbit) uswtmp |= mask;
mask <<=1;
if(mask == 0){
if(uswidx < USWNRXB) uswbyte[uswidx]=uswtmp;
// if(uswidx < USWNRXB) *puswbyte++ = uswtmp; // Occupa di più
mask=0xff;
}
}
uswmask=mask;
// cbi(PORTD,4);
};
}
ISR(PCINT2_vect){
if((PIND & 4) == 0) {
OCR0A = TCNT0+USWBRT+USWSTA;
cbi(PCMSK2, PCINT18);
uswmask = 1;
uswtmp=0;
}
}