#include <wiring_private.h>
// pin pulsanti
#define PM PC0
#define PS PC1
// pin uscita e debug
#define PB PD7
#define PO PB5
#define PINCEE PB0
#define PINTEN PB1
#define PTMREN PB2
#define PDTICH PB3
#define PDTIT0 PB4
#define PMSK ((1<<PM)|(1<<PS))
#define PUL_NUM 8
#define DONTCARE 0
#define T0PRE 3
// tipi input pulsante
#define PINCH 0
#define FILTER_TEXP 1
#define STAB_TEXP 2
#define PRESS_TEXP 3
// tipi output pulsante
#define EVCH_CATCH 1
#define EVTEXP_CATCH 2
// stati pulsante
#define REST 0
#define FILTER 1
#define WAIT_STAB 2
#define PRESSED 3
void init(void);
void initModTasti(void);
volatile uint8_t port_state;
volatile uint8_t pul_state[PUL_NUM];
int main() {
init();
sei();
while (1) {
uint8_t pul_state0_ = pul_state[0];
uint8_t pul_state1_ = pul_state[1];
if (pul_state0_ == PRESSED)
cbi(PORTB,PO);
else
sbi(PORTB,PO);
if (pul_state1_ == PRESSED)
cbi(PORTD,PB);
else
sbi(PORTD,PB);
if(TCCR0B)
sbi(PORTB,PTMREN);
else
cbi(PORTB,PTMREN);
if(PCMSK1&PMSK)
sbi(PORTB,PINTEN);
else
cbi(PORTB,PINTEN);
}
}
/* void printByte(uint8_t n){
//
leggi V
se output !aggiornato
ripeti
c=cifra(V,i++)
fino a c==0 && i<cifreNumero 0000\0821
stampa(c+'0')
attendi stampa
mentre i<cifreNumero
c=cifra(V,i++)
stampa(c+'0')
attendi stampa
ripeti
output aggiornato
if s==0
str[cifreNumero]
atoi(num,&str[0],10)
i=cifre-1
mentre c=str[i]=='0' && i>0, i--
stampa(c)
s=1
elseif s==1
if okw, s=2
elseif s==2
if i<cifreNumero
c=cifra(V,i++)
stampa(c+'0')
s=1
else
s=3
//
static uint8_t n_;
if (s==0){
n_=n;
itoa(n_,&strcifre[0],10);
uint8_t i=0;
while(strcifre[i]!='\0') i++;
strcifre[i++]=' ';
strcifre[i++]='\0';
s=2;
icifra=0;
}
if (s==1){
if(strcifre[icifra]!='\0'){
UDR0=strcifre[icifra++];
s=2;
}else
s=3;
}else if (s==2){
if (UCSR0A&(1<<UDRE0))
s=1;
}
}*/
ISR(PCINT1_vect) {
/*
PINx_corrente=PINx
pins_evento=PCMSK1 & (PINx_precedente ^ PINx_corrente)
PCMSK1 &= ~pins_evento
se pins_evento
ripeti
zerosig_primoauno=pins_evento^-(uint8_t)pins_evento
(bitn=primo bit==1 in pins_evento)
bitn=binsrch(zerosig_primoauno)
stato_automaN=stato_automi_pulsante[bitn]
stato_automi_pulsante[bitn]=automa_pulsante_tran(stato_automaN)
pins_evento^=~zerosig_primoauno
mentre pins_evento!=0
altrimenti
non sono consistenti PINx_precedente o PINx_corrente
*/
/*
L'automa pulsante non deve essere legato al tempo,
implementa solo la logica, lo stato della porta
deve essere seguito da un'automa separato che resitutisce
tutte le informazioni in tempo reale, come i cambiamenti pin,
e la validità dello stato che espone; al massimo il primo si
sincronizza o fa polling dello stato porta o risponde ad eventi a
cui si interessa.
..quindi:
Descizione
0)
attendi pinChange
leggi porta
se la porta non è cambiata
(capita che la linea cambia troppo velocemente e il
valore letto subito appena eseguita l'isr sia già in
ritardo -> nell'isr non si rilevano pin cambiati)
fai
per ogni dt (inizio polling temporizzato)
leggi porta
fino a porta cambiata
rileva quali pin hanno generato l'interrupt
registra evento/validità etc.
aggiorna porta
vai a 0)
Analisi del problema:
portaCorrente=leggi porta
if porta_corrente==stato_porta
stato_porta_valido=false
do
while t<t0+dt; t++;
porta_corrente=leggi porta
while porta_corrente==stato_porta
pin_cambiati=(i,j,k,...), pin in PIN_PORTA={0,1,2,3,4,5,6,7}
stato_porta_valido=true
State chart:
*/
uint8_t port_cur_ = PINC;
sbi(PORTB,PDTICH);//dbg***
uint8_t intmask_ = PCMSK1;
uint8_t port_ch_ = intmask_ & (port_state ^ port_cur_);
if(!port_ch_){
port_ch_ = PMSK;
sbi(PORTB,PINCEE);//dbg***
}else cbi(PORTB,PINCEE);//dbg***
port_state = port_cur_;
/*port_ch_,intmask_*/
uint8_t exp_catch_ = 0;
do {
uint8_t first_pinch_ = port_ch_ & -(int8_t)port_ch_;
uint8_t pulp_ = bitpos8(first_pinch_);
uint8_t pul_state_ = pul_state[pulp_];
uint8_t pul_out_ = pul_fout(pul_state_);
if (pul_out_ & EVCH_CATCH);
else
intmask_ &= ~first_pinch_;
if(exp_catch_);
else
exp_catch_ = pul_out_ & EVTEXP_CATCH;
pul_state[pulp_] = pul_tran(pul_state_, DONTCARE, PINCH);
port_ch_ ^= first_pinch_;
} while (port_ch_);
/*intmask_,exp_catch_*/
PCMSK1 = intmask_;
if(exp_catch_){
TCCR0B = T0PRE;
} else {
TCCR0B = 0;
TCNT0 = 0;
}
cbi(PORTB,PDTICH);//dbg***
}
uint8_t bitpos8(uint8_t hot_one) {
// switch (hot_one) {
// case 1: hot_one = 0; break;
// case 2: hot_one = 1; break;
// case 4: hot_one = 2; break;
// case 8: hot_one = 3; break;
// case 16: hot_one = 4; break;
// case 32: hot_one = 5; break;
// case 64: hot_one = 6; break;
// case 128: hot_one = 7;
// }
if(hot_one>8){
if(hot_one>32){
if(hot_one>64){
hot_one=7;
}else{
hot_one=6;
}
}else{
if(hot_one>16){
hot_one=5;
}else{
hot_one=4;
}
}
}else{
if(hot_one>4){
hot_one=3;
}else{
hot_one--;
}
}
return hot_one;
}
uint8_t pul_tran(uint8_t s, uint8_t vline, uint8_t inp) {
if (inp == PINCH)
s = FILTER;
else {
switch (s) {
case FILTER:
if (inp == FILTER_TEXP)
s = WAIT_STAB;
break;
case WAIT_STAB:
if (inp == STAB_TEXP) {
if (vline)
s = REST;
else
s = PRESSED;
}
}
}
return s;
}
uint8_t pul_fout(uint8_t s) {
switch (s) {
case REST: s = EVCH_CATCH; break;
case FILTER: s = EVTEXP_CATCH; break;
case WAIT_STAB: s = EVCH_CATCH | EVTEXP_CATCH; break;
case PRESSED: s = EVCH_CATCH;
}
return s;
}
ISR(TIMER0_OVF_vect) {
sbi(PORTB,PDTIT0);//dbg***
uint8_t port_cur_ = PINC;
GPIOR0 = PCMSK1;
uint8_t texp_catch_ = 0;
uint8_t i_bitmask_ = 1;
uint8_t pul_mask_ = PMSK;
for (uint8_t i = 0; pul_mask_; i++){
if (pul_mask_ & i_bitmask_){
uint8_t pul_state_ = pul_state[i];
int8_t pul_inp_ = -1;
if (pul_state_ == WAIT_STAB) {
pul_inp_ = STAB_TEXP;
} else if (pul_state_ == FILTER) {
pul_inp_ = FILTER_TEXP;
} else {
//passare PRESS_TEXP
}
if (pul_inp_ != -1) {
uint8_t pul_out_ = pul_fout(pul_state_);
if (pul_out_ & EVCH_CATCH)
sbi(GPIOR0, i);
else
cbi(GPIOR0, i);
if(texp_catch_);
else
texp_catch_ = pul_out_ & EVTEXP_CATCH;
pul_state[i] = pul_tran(pul_state_, port_cur_&i_bitmask_, pul_inp_);
}
pul_mask_ &= ~i_bitmask_;
}
i_bitmask_ <<= 1;
}
port_state = port_cur_;
PCMSK1 = GPIOR0;
if(!texp_catch_){
TCCR0B = 0;
}
cbi(PORTB,PDTIT0);//dbg***
}
void init(void) {
// porta c
DDRC |= 0xFC;
// porta b,d
DDRB = 0xFF;
DDRD = 0xFC;
UBRR0H = (uint8_t)(416 >> 8);
UBRR0L = (uint8_t)(416 & 0xFF);
sbi(UCSR0B, TXEN0); // enable usart tx
initModTasti();
}
void initModTasti(void) {
// porta c
sbi(PORTC, PM); // pullup
sbi(PORTC, PS);
sbi(PCICR, PCIE1); // abilita pin change int su porta c
PCMSK1 |= PMSK; // abilita su PM e PS
// timer 0
sbi(TIMSK0, TOIE0); // abilita int ovf T0
TCCR0B = T0PRE;
}