xilebo noone | bonjour,
je developpe actuellement une application sous linux necessitant le port infra rouge et apres avoir galéré a installer lirc dessus, ca ne marche finalement pas. Ou plutot tout marche mais je ne recois pas correctement les signaux.
ex :
j envoie un signal codé en RC5 (il faut savoir que le RC5 code ses bits avec des fronts montant et descendant de 889 µs, donc je suis censé recevoir des PULSE et des SPACES d environ 889µs +- delta OU 2*889=1778µs +- delta), et je recois des donnees completement differentes (a savoir sur une autre machine avec d autres composants ca marche tres bien).
Mais je recois quelque chose qui "ressemble" : je m explique
si j etais censé recevoir :
SPACE 16777216
PULSE 889
SPACE 889
PULSE 889
SPACE 1778
PULSE 889
SPACE 889
PULSE 1778
SPACE 1778
je recois a la place SPACE 1677216
PULSE 39
SPACE 1700
PULSE 39
SPACE 1765
PULSE 39
SPACE 2643
PULSE 39
etc...
J ai donc remarqué que les temps entre 2 pulses (somme de pulse + space ) etait le meme (+- delta je precise) entre ce que j emets et ce que je receptionne. Autrement dit, l interruption se produit bien mais le temps calculé pour le pulse est faux. D ailleurs je precise que la valeur "39" n est pas une valeur anodine mais exactement egale a la moitié d'une constante dans le driver soit 9bits * 1 sec / 115200 bits = 78,25 ms j ai donc decidé de "completer" le driver pour qu il puisse fonctionner avec mon controleur IR (car j ai pas le choix) mais j avoue que dans le source, quelques choses me laissent perplexes :
voici le source de la fonction invoquée lors d'une interruption (le define LIRC_SA1100 concerne les PDA de type Ipaq donc a ignorer)
Code :
- static void sir_interrupt(int irq, void * dev_id, struct pt_regs * regs)
- {
- unsigned char data;
- struct timeval curr_tv;
- static unsigned long deltv;
- #ifdef LIRC_ON_SA1100
- int status;
- static int n=0;
- //printk("interrupt\n" );
- status = Ser2UTSR0;
- /*
- * Deal with any receive errors first. The bytes in error may be
- * the only bytes in the receive FIFO, so we do this first.
- */
- while (status & UTSR0_EIF)
- {
- int bstat;
- #ifdef DEBUG
- printk("EIF\n" );
- bstat = Ser2UTSR1;
- if (bstat & UTSR1_FRE)
- printk("frame error\n" );
- if (bstat & UTSR1_ROR)
- printk("receive fifo overrun\n" );
- if(bstat&UTSR1_PRE)
- printk("parity error\n" );
- #endif
- bstat = Ser2UTDR;
- n++;
- status = Ser2UTSR0;
- }
- if (status & (UTSR0_RFS | UTSR0_RID))
- {
- do_gettimeofday(&curr_tv);
- deltv = delta(&last_tv, &curr_tv);
- do
- {
- #ifdef DEBUG_SIGNAL
- printk(KERN_DEBUG LIRC_DRIVER_NAME": t %lu , d %d\n",
- deltintrtv,(int)data);
- #endif
- data=Ser2UTDR;
- //printk("data: %d\n",data);
- n++;
- }
- while(status&UTSR0_RID && /* do not empty fifo in
- order to get UTSR0_RID in
- any case */
- Ser2UTSR1 & UTSR1_RNE); /* data ready */
- if(status&UTSR0_RID)
- {
- //printk("add\n" );
- add_read_queue(0,deltv-n*TIME_CONST); /*space*/
- add_read_queue(1,n*TIME_CONST); /*pulse*/
- n=0;
- last_tv=curr_tv;
- }
- }
- if (status & UTSR0_TFS) {
- printk("transmit fifo not full, shouldn't ever happen\n" );
- }
- /*
- * We must clear certain bits.
- */
- status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
- if (status)
- Ser2UTSR0 = status;
- #else
- unsigned long deltintrtv;
- unsigned long flags;
- int iir, lsr;
- while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {
- switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */
- case UART_IIR_MSI:
- (void) inb(io + UART_MSR);
- break;
- case UART_IIR_RLSI:
- (void) inb(io + UART_LSR);
- break;
- case UART_IIR_THRI:
- #if 0
- if (lsr & UART_LSR_THRE) /* FIFO is empty */
- outb(data, io + UART_TX)
- #endif
- break;
- case UART_IIR_RDI:
- /* avoid interference with timer */
- spin_lock_irqsave(&timer_lock, flags);
- do
- {
- del_timer(&timerlist);
- data = inb(io + UART_RX);
- do_gettimeofday(&curr_tv);
- deltv = delta(&last_tv, &curr_tv);
- deltintrtv = delta(&last_intr_tv, &curr_tv);
- #ifdef DEBUG_SIGNAL
- printk(KERN_DEBUG LIRC_DRIVER_NAME": t %lu , d %d\n",deltintrtv,(int)data);
- #endif
- /* if nothing came in last 2 cycles,
- it was gap */
- if (deltintrtv > TIME_CONST * 2) {
- if (last_value) {
- #ifdef DEBUG_SIGNAL
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": GAP\n" );
- #endif
- /* simulate signal change */
- add_read_queue(last_value,
- deltv-
- deltintrtv);
- last_value = 0;
- last_tv.tv_sec = last_intr_tv.tv_sec;
- last_tv.tv_usec = last_intr_tv.tv_usec;
- deltv = deltintrtv;
- }
- }
- data = 1;
- if (data ^ last_value) {
- /* deltintrtv > 2*TIME_CONST,
- remember ? */
- /* the other case is timeout */
- add_read_queue(last_value,
- deltv-TIME_CONST);
- last_value = data;
- last_tv = curr_tv;
- if(last_tv.tv_usec>=TIME_CONST)
- {
- last_tv.tv_usec-=TIME_CONST;
- }
- else
- {
- last_tv.tv_sec--;
- last_tv.tv_usec+=1000000-
- TIME_CONST;
- }
- }
- last_intr_tv = curr_tv;
- if (data)
- {
- /* start timer for end of sequence detection */
- timerlist.expires = jiffies + SIR_TIMEOUT;
- add_timer(&timerlist);
- }
- }
- while ((lsr = inb(io + UART_LSR))
- & UART_LSR_DR); /* data ready */
- spin_unlock_irqrestore(&timer_lock, flags);
- break;
- default:
- break;
- }
- }
- #endif
- }
|
* a un moment dans le do .. while on a un truc du genre
Code :
- data = inb(io + UART_RX);
|
je ne suis pas (encore) expert dans l ecriture des modules, mais si j ai bien compris, cela permet de lire une valeur IO a l adresse io (l adresse io de mon peripherique = l adresse io de mon controleur IR spécifiée dans le bios)
mais plus loin dans le code , on s apercoit qu on ecrase la valeur data (data=1 sans avoir testé cette valeur auparavant... quel interet ? (j ai pas compris)
* juste apres je vois le test :
Code :
- if (data ^ last_value)
|
c est un XOR bit a bit il me semble. Sachant que data vaut forcement 1 , cela signifie donc qu on passe dans le if si le premier bit de last_value est a 0 .. donc pourquoi ce test ?
* a un moment , on a : "if nothing came in last 2 cycles, it was gap " Je ne comprends pas ce que signifie cette phrase... apparemment a chaque interruption il passe dedans OR il ne devrait pas passer dedans.Quelqu un peut m eclairer ?
* enfin, je n ai pas trouvé de doc parlant des constantes du genre UART_RX
UART_LSR
UART_IIR_RDI etc...
quelqu un peut il me dire ou trouver de la doc ?
merci de m aider car je ne comprends pas bien l interet de l algo permettant de calculer le temps du PULSE et le temps du SPACE.
merci d avoir lu jusque la ;-) |