Go Down

Topic: Libreria wishield 2.0 con Atmega644/1284 (Read 2381 times) previous topic - next topic

superzaffo

Ciao ragazzi, ho bisogno di modificare la libreria della wishield 2.0 per l' ATMEGA644 e/o 1284.
All' origine era stata creata per il 328 e in rete sono riuscito a recuperare quella modificata per atmega2560. http://techrm.blogspot.it/2012/12/how-to-interface-arduino-mega-2560-to.html
Praticamente avrei bisogno di modificare la parte SPI.H della libreria in cui ci sono i riferimenti in esdecimale degli indirizzi dei vari pin del SPI e l' eventuale riferimento all' int0. La wishield si connetteva al 328 ai classici pin spi e anche al pin2 per l' int0, quindi penso che sia da modificare anche il riferimento per l' int0.
Purtroppo le mie conoscenze di questi processori non arrivano a tanto (per il momento  ;) ) e quindi avrei bisogno del vostro aiuto.
Vi allego i file SPI.H originale e quello modificato per il 2560. Inoltre vi posto anche la parte che penso sia da modificare.
questa è la parte del file per il 2560
Code: [Select]

// Uncomment one line below to
    // specify which Arduino pin
    // to use as WiShield interrupt
    #define USE_DIG0_INTR      // use digital pin 0
    //#define USE_DIG8_INTR      // use digital pin 8


    #ifdef USE_DIG0_INTR
    #define ZG2100_ISR_DISABLE()   (EIMSK &= ~(0x01))
    #define ZG2100_ISR_ENABLE()      (EIMSK |= 0x01)
    #define ZG2100_ISR_GET(X)      (X = EIMSK)
    #define ZG2100_ISR_SET(X)      (EIMSK = X)
    #endif

    #ifdef USE_DIG8_INTR
    #define ZG2100_ISR_DISABLE()   (PCMSK0 &= ~(0x01))
    #define ZG2100_ISR_ENABLE()      (PCMSK0 |= 0x01)
    #define ZG2100_ISR_GET(X)      (X = PCMSK0)
    #define ZG2100_ISR_SET(X)      (PCMSK0 = X)
    #endif

    //AVR Mega168 SPI HAL
    #define BIT0                     0x01
    #define BIT1                     0x02
    #define BIT2                     0x04
    #define BIT3                     0x08
    #define BIT4                     0x10
    #define BIT5                     0x20
    #define BIT6                     0x40
    #define BIT7                     0x80

    #ifdef USE_DIG8_INTR
    #define ZG2100_INTR                  BIT0
    #endif

    //#define SPI0_SS_BIT                  BIT2
    #define SPI0_SS_BIT                  BIT0
    #define SPI0_SS_DDR                  DDRB
    #define SPI0_SS_PORT               PORTB

    //#define SPI0_SCLK_BIT               BIT5
    #define SPI0_SCLK_BIT               BIT1
    #define SPI0_SCLK_DDR               DDRB
    #define SPI0_SCLK_PORT               PORTB

    //#define   SPI0_MOSI_BIT               BIT3
    #define   SPI0_MOSI_BIT               BIT2
    #define SPI0_MOSI_DDR               DDRB
    #define SPI0_MOSI_PORT               PORTB

    //#define   SPI0_MISO_BIT               BIT4
    #define   SPI0_MISO_BIT               BIT3
    #define SPI0_MISO_DDR               DDRB
    #define SPI0_MISO_PORT               PORTB



e questa è la parte originale per il 328.
Code: [Select]

// Uncomment one line below to
// specify which Arduino pin
// to use as WiShield interrupt
#define USE_DIG0_INTR // use digital pin 0
//#define USE_DIG8_INTR // use digital pin 8


#ifdef USE_DIG0_INTR
#define ZG2100_ISR_DISABLE() (EIMSK &= ~(0x01))
#define ZG2100_ISR_ENABLE() (EIMSK |= 0x01)
#define ZG2100_ISR_GET(X) (X = EIMSK)
#define ZG2100_ISR_SET(X) (EIMSK = X)
#endif

#ifdef USE_DIG8_INTR
#define ZG2100_ISR_DISABLE() (PCMSK0 &= ~(0x01))
#define ZG2100_ISR_ENABLE() (PCMSK0 |= 0x01)
#define ZG2100_ISR_GET(X) (X = PCMSK0)
#define ZG2100_ISR_SET(X) (PCMSK0 = X)
#endif

//AVR Mega168 SPI HAL
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80

#ifdef USE_DIG8_INTR
#define ZG2100_INTR BIT0
#endif

#define SPI0_SS_BIT BIT2
#define SPI0_SS_DDR DDRB
#define SPI0_SS_PORT PORTB

#define SPI0_SCLK_BIT BIT5
#define SPI0_SCLK_DDR DDRB
#define SPI0_SCLK_PORT PORTB

#define SPI0_MOSI_BIT BIT3
#define SPI0_MOSI_DDR DDRB
#define SPI0_MOSI_PORT PORTB

#define SPI0_MISO_BIT BIT4
#define SPI0_MISO_DDR DDRB
#define SPI0_MISO_PORT PORTB


#define SPI0_WaitForReceive()
#define SPI0_RxData() (SPDR)

#define SPI0_TxData(Data) (SPDR = Data)
#define SPI0_WaitForSend() while( (SPSR & 0x80)==0x00 )

#define SPI0_SendByte(Data) SPI0_TxData(Data);SPI0_WaitForSend()
#define SPI0_RecvBute() SPI0_RxData()

// PB4(MISO), PB3(MOSI), PB5(SCK), PB2(/SS)         // CS=1, waiting for SPI start // SPI mode 0, 8MHz
#ifdef USE_DIG8_INTR
#define SPI0_Init() DDRB  |= SPI0_SS_BIT|SPI0_SCLK_BIT|SPI0_MOSI_BIT|LEDConn_BIT;\
DDRB  &= ~(SPI0_MISO_BIT|ZG2100_INTR);\
PORTB = SPI0_SS_BIT;\
SPCR  = 0x50;\
SPSR  = 0x01
#else
#define SPI0_Init() DDRB  |= SPI0_SS_BIT|SPI0_SCLK_BIT|SPI0_MOSI_BIT|LEDConn_BIT;\
DDRB  &= ~SPI0_MISO_BIT;\
PORTB = SPI0_SS_BIT;\
SPCR  = 0x50;\
SPSR  = 0x01
#endif


se mi potete dar una mano vi ringrazio fin d'ora.

leo72

Prova questo:

Code: [Select]
// Uncomment one line below to
// specify which Arduino pin
// to use as WiShield interrupt
#define USE_DIG0_INTR      // use digital pin 0
//#define USE_DIG8_INTR      // use digital pin 8

#ifdef USE_DIG0_INTR
#define ZG2100_ISR_DISABLE()   (EIMSK &= ~(0x01))
#define ZG2100_ISR_ENABLE()      (EIMSK |= 0x01)
#define ZG2100_ISR_GET(X)      (X = EIMSK)
#define ZG2100_ISR_SET(X)      (EIMSK = X)
#endif

#ifdef USE_DIG8_INTR
#define ZG2100_ISR_DISABLE()   (PCMSK0 &= ~(0x01))
#define ZG2100_ISR_ENABLE()      (PCMSK0 |= 0x01)
#define ZG2100_ISR_GET(X)      (X = PCMSK0)
#define ZG2100_ISR_SET(X)      (PCMSK0 = X)
#endif

//AVR Mega168 SPI HAL
#define BIT0                     0x01
#define BIT1                     0x02
#define BIT2                     0x04
#define BIT3                     0x08
#define BIT4                     0x10
#define BIT5                     0x20
#define BIT6                     0x40
#define BIT7                     0x80

#ifdef USE_DIG8_INTR
#define ZG2100_INTR                  BIT0
#endif

#define SPI0_SS_BIT                  BIT4
#define SPI0_SS_DDR                  DDRB
#define SPI0_SS_PORT               PORTB

#define SPI0_SCLK_BIT               BIT7
#define SPI0_SCLK_DDR               DDRB
#define SPI0_SCLK_PORT               PORTB

#define   SPI0_MOSI_BIT               BIT5
#define SPI0_MOSI_DDR               DDRB
#define SPI0_MOSI_PORT               PORTB

#define   SPI0_MISO_BIT               BIT6
#define SPI0_MISO_DDR               DDRB
#define SPI0_MISO_PORT               PORTB

superzaffo

Grazie leo... appena posso provo la cosa. Tra un paio di giorni penso, da oggi sono fuori per lavoro. Ma ti farò sicuramente sapere
Ma fammi capire una cosa.. ieri sera (meglio dire notte :-) ) mi sono letto parte dei datasheet e se ho ben capito i pin degli atmel sono raggruppati in port e su queste port a seconda del numero di bit si seleziona il pin. E' corretto ?
Altra cosa...
Nella libreria originale per il 328P io dovevo connettere il pin INT  del chip wi-fi al pin 2 dell' arduino. Questo perchè, penso, utilizza l' int0 del micro.
La libreria modificata ho visto, dalle foto, vuole sempre il pin 2 dell' arduino mega2560 anche se fa riferimento all' int4.
Secondo te, nel 644 dovrò sempre collegarlo al pin2 o devo far riferimento al numero d' INT ?

grazie ancora

superzaffo

Per il momento, sulla modifica dell' interrupt ho trovato questo
http://www.linksprite.com/article/shownews.php?lang=en&id=106
Quello che non capisco è che secondo quanto dice, devo modificare la libreria per il pin 21, che in teoria dal datasheet, dovrebbe essere l' int0 ma poi mi fa modificare il codice per mettere int2, perchè dal riferimento dell' ide di arduino questo mappa il 21 con int2...
Se qualcuno mi può spiegare il perchè e che cosa devo mettere come rifferimento int nel 644..  :smiley-roll-sweat:
Grazie

superzaffo

Nessuno che ha qualche idea sul numero che devo inserire nella attachinterupt per usare l' int2 ?  :smiley-fat:

leo72


Grazie leo... appena posso provo la cosa. Tra un paio di giorni penso, da oggi sono fuori per lavoro. Ma ti farò sicuramente sapere
Ma fammi capire una cosa.. ieri sera (meglio dire notte :-) ) mi sono letto parte dei datasheet e se ho ben capito i pin degli atmel sono raggruppati in port e su queste port a seconda del numero di bit si seleziona il pin. E' corretto ?

Diciamo che i pin sono mappati in memoria dentro a particolari registri dove puoi leggere/scrivere e le modifiche fatte ai singoli bit si riflettono sulle porte fisiche e viceversa.
Se scrivi "1" sul bit corrispondente ad un certo pin di una data porta, puoi attivare quel pin come output oppure scriversi il valore High.

Quote

Altra cosa...
Nella libreria originale per il 328P io dovevo connettere il pin INT  del chip wi-fi al pin 2 dell' arduino. Questo perchè, penso, utilizza l' int0 del micro.

Non è corretto. Gli interrupt esterni di tipo INT sono agganciati a determinati pin, non puoi cambiarli tu. Nel caso dell'Atmega328 l'INT0 è agganciato al pin PD2.

Quote

La libreria modificata ho visto, dalle foto, vuole sempre il pin 2 dell' arduino mega2560 anche se fa riferimento all' int4.
Secondo te, nel 644 dovrò sempre collegarlo al pin2 o devo far riferimento al numero d' INT ?

Forse per compatibilità fra schede, visto che il pin D2 dell'Arduino UNO corrisponde al pin D2 dell'Arduino MEGA ma questi 2 pin non corrispondono agli stessi piedini fisici del microcontrollore, visto che sono differenti.
Difatti se vedi la piedinatura dell'Arduino MEGA
http://arduino.cc/en/Hacking/PinMapping2560
ti accorgi che il pin D2 è agganciato al pin PB4 del chip, su cui c'è appunto l'INT4.

Siccome la lib non è nata per i 644/1284 (così mi pare) ti consiglio di agganciare quel segnale al pin PD2 del chip, dove c'è appunto l'INT0.

leo72


Per il momento, sulla modifica dell' interrupt ho trovato questo
http://www.linksprite.com/article/shownews.php?lang=en&id=106
Quello che non capisco è che secondo quanto dice, devo modificare la libreria per il pin 21, che in teoria dal datasheet, dovrebbe essere l' int0 ma poi mi fa modificare il codice per mettere int2, perchè dal riferimento dell' ide di arduino questo mappa il 21 con int2...
Se qualcuno mi può spiegare il perchè e che cosa devo mettere come rifferimento int nel 644..  :smiley-roll-sweat:
Grazie

Stiamo parlando di MEGA? Io sul pin D21 vedo l'INT0, l'INT2 è sul pin D19.

superzaffo

Inanzi tutto, grazie Leo per le tue risposte.
Si si parla di mega, ma da quanto dice il link
Quote

(3) In "WiServer.cpp" and "WiShield.cpp" change "attachInterrupt(0, zg_isr, LOW);" to "attachInterrupt(2, zg_isr, LOW);". This may be counterintutive, but from the documentation, it seems the Arduino development environment maps interrupt pin 2 to 21. See http://www.arduino.cc/en/Reference/AttachInterrupt for details.

che a livello di compilazione, l' ide mappa in un altro modo gli int. Ovvero se non è un arduino uno, se vuoi l'interupt 0 del processore devi mettere 2 nel numero di interupt nell' ide (ttachInterrupt(2, zg_isr, LOW);" così lo mappa nel pin arduino 21 che si riferisce all' int0 e non int2.
Guarda questo... http://arduino.cc/forum/index.php?action=printpage;topic=145003.0
In questo caso fanno rifermento al processore 644, che è quello che voglio utilizzare io.
Ho potuto per il momento guardare il winterupts.c
Quote

#if defined(__AVR_ATmega32U4__)
   // I hate doing this, but the register assignment differs between the 1280/2560
   // and the 32U4.  Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
   // even present on the 32U4 this is the only way to distinguish between them.
   case 0:
      EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
      EIMSK |= (1<<INT0);
      break;
   case 1:
      EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
      EIMSK |= (1<<INT1);
      break;   
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
    case 2:
      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      EIMSK |= (1 << INT0);
      break;
    case 3:
      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      EIMSK |= (1 << INT1);
      break;
    case 4:
      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      EIMSK |= (1 << INT2);

Praticamente se non è un 32U4 il case per il 2 seleziona l' INT0 e per il 4 l' INT4.
Quindi se io scrivo attachinterrupt(2,..) selezione l' attachinterrupt(4,...) vado a selezionare  l' INT2 per cui cambiano anche i pin.
Almeno per qyuello che ho potuto capire e approfondire alla sera/notte :-)
In questo week end dovrei avere il tempo di fare qualche prova e quindi poi ti dico.


leo72

1) la piedinatura non mente, sul piedino fisico PD0 c'è l'INT0 del microcontrollore, su quel pin c'è l'INT0. Quindi il team di Arduino, per compatibilità fra Uno/Leonardo/Mega ecc.. ha deciso che attivando l'INT2 in realtà si attivi l'INT0 e viceversa. Quindi scrivendo attachInterrupt(2...) in realtà tu attivi l'INT0. Nel file WInterrupt c'è spiegato che è c'entra il modo in cui sono individuati gli interrupt ed i relativ pin.
Il check non termina però col codice che hai messo ma è molto più lungo e complesso:
Code: [Select]

   switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
// I hate doing this, but the register assignment differs between the 1280/2560
// and the 32U4.  Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// even present on the 32U4 this is the only way to distinguish between them.
case 0:
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
EIMSK |= (1<<INT0);
break;
case 1:
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
EIMSK |= (1<<INT1);
break;
    case 2:
        EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
        EIMSK |= (1<<INT2);
        break;
    case 3:
        EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
        EIMSK |= (1<<INT3);
        break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
    case 2:
      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      EIMSK |= (1 << INT0);
      break;
    case 3:
      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      EIMSK |= (1 << INT1);
      break;
    case 4:
      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      EIMSK |= (1 << INT2);
      break;
    case 5:
      EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
      EIMSK |= (1 << INT3);
      break;
    case 0:
      EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
      EIMSK |= (1 << INT4);
      break;
    case 1:
      EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
      EIMSK |= (1 << INT5);
      break;
    case 6:
      EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
      EIMSK |= (1 << INT6);
      break;
    case 7:
      EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
      EIMSK |= (1 << INT7);
      break;
#else
    case 0:
    #if defined(EICRA) && defined(ISC00) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      EIMSK |= (1 << INT0);
    #elif defined(MCUCR) && defined(ISC00) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      GICR |= (1 << INT0);
    #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      GIMSK |= (1 << INT0);
    #else
      #error attachInterrupt not finished for this CPU (case 0)
    #endif
      break;

    case 1:
    #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      EIMSK |= (1 << INT1);
    #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      GICR |= (1 << INT1);
    #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      GIMSK |= (1 << INT1);
    #else
      #warning attachInterrupt may need some more work for this cpu (case 1)
    #endif
      break;
   
    case 2:
    #if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      EIMSK |= (1 << INT2);
    #elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      GICR |= (1 << INT2);
    #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      GIMSK |= (1 << INT2);
    #endif
      break;
#endif
    }
  }

Come vedi sono analizzate un sacco di combinazioni di registri e bit per determinare con che micro si ha a che fare, tolto l'Atmega32U4 che viene trattato a parte rispetto agli altri.

2) L'ATmega644/1824 hanno un supporto da parte del core introdotto di recente, fino all'IDE 1.0.2 si doveva ricorrere ad un core esterno. Ci sta che ci siano ancora delle cose lasciare a mezzo o non implementate del tutto.

Go Up