Subversion Repositories HomeAutomation

Rev

Rev 1463 | Rev 1485 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * PCA95xx device driver. Provides possibility for several independent users of the
  3.  * device.
  4.  *
  5.  * @author  Anders Runeson
  6.  *
  7.  * @date    2010-04-02
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. #include <inttypes.h>
  14. #include <avr/io.h>
  15. #include <avr/interrupt.h>
  16.  
  17. #include <drivers/io/PCA95xx.h>
  18.  
  19.  
  20. /*-----------------------------------------------------------------------------
  21.  * Globals
  22.  *---------------------------------------------------------------------------*/
  23. volatile uint8_t Pca95xx_address;
  24. volatile uint16_t Pca95xx_direction;
  25. volatile uint16_t Pca95xx_outputs;
  26.  
  27. #if PCA95XX_NUM_CALLBACKS > 0
  28. volatile pca95xxCallback_t[PCA95XX_NUM_CALLBACKS] Pca95xx_callback;
  29. #endif
  30.  
  31.  
  32. /*-----------------------------------------------------------------------------
  33.  * Interrupt Service Routines
  34.  *---------------------------------------------------------------------------*/
  35. #if PCA95XX_NUM_CALLBACKS > 0
  36. ISR(PCA_INT_VECTOR)
  37. {
  38.     uint8_t t;
  39.     /* Read input registers from device */
  40.     //TODO: communication with device
  41.     uint16_t inputs = ;
  42.    
  43.     /* Call all callbacks with the input as argument */
  44.     for (t = 0; t < PCA95XX_NUM_CALLBACKS; t++)
  45.     {
  46.         Pca95xx_callback[t](inputs);
  47.     }
  48. }
  49. #endif
  50.  
  51. /*-----------------------------------------------------------------------------
  52.  * Public Functions
  53.  *---------------------------------------------------------------------------*/
  54.  
  55. void Pca95xx_Init(uint8_t address)
  56. {
  57.     unsigned char messageBuf[5];
  58.  
  59.     /* Disable interrupts while tampering with the global vars */
  60.     uint8_t sreg = SREG;
  61.     cli();
  62.  
  63.     /* Store address */
  64.     Pca95xx_address = (PCA95xx_I2C_DEV_ADDR|(address&7));
  65.    
  66.     /* Set up interrupt */
  67. #if PCA_INT_VECTOR==INT0_vect
  68.     PORTD|=(1<<PORT2);  /* setup pullup */
  69. #else
  70.     PORTD|=(1<<PORT3);  /* setup pullup */
  71. #endif
  72.     /* Set up ports? */
  73.     TWI_Master_Initialise();
  74.    
  75.     /* Read output registers from device to global var */
  76.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  77.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  78.     TWI_Start_Read_Write( messageBuf, 2 );
  79.     while ( TWI_Transceiver_Busy() );
  80.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  81.     TWI_Start_Read_Write( messageBuf, 3 );
  82.     while ( TWI_Transceiver_Busy() );
  83.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  84.     {
  85.         Pca95xx_outputs = (messageBuf[2]<<8)|messageBuf[1];
  86.     }
  87.  
  88.     /* Read direction registers from device to global var */
  89.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  90.     messageBuf[1] = PCA95xx_REG_CONF0;
  91.     TWI_Start_Read_Write( messageBuf, 2 );
  92.     while ( TWI_Transceiver_Busy() );
  93.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  94.     TWI_Start_Read_Write( messageBuf, 3 );
  95.     while ( TWI_Transceiver_Busy() );
  96.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  97.     {
  98.         Pca95xx_direction = (messageBuf[2]<<8)|messageBuf[1];
  99.     }
  100.    
  101.     /* Enable interrupt */
  102. #if PCA95XX_NUM_CALLBACKS > 0
  103.     PCA_INT_ENABLE();
  104. #endif
  105.     SREG = sreg;
  106. }
  107.  
  108. /*---------------------------------------------------------------------------*/
  109.  
  110. #if PCA95XX_NUM_CALLBACKS > 0
  111. void Pca95xx_SetCallback(uint8_t index, pca95xxCallback_t callback)
  112. {
  113.     /* Disable interrupts while tampering with the global vars */
  114.     uint8_t sreg = SREG;
  115.     cli();
  116.  
  117.     if (index < PCA95XX_NUM_CALLBACKS)
  118.     {
  119.         /* Store the callback */
  120.         Pca95xx_callback[index] = callback;
  121.     }
  122.  
  123.     SREG = sreg;
  124. }
  125. #endif
  126.  
  127. /*---------------------------------------------------------------------------*/
  128.  
  129. uint16_t Pca95xx_GetInputs(void)
  130. {
  131.     unsigned char messageBuf[5];
  132.  
  133.     /* Disable device interrupts while communicating with the device */
  134.     PCA_INT_DISABLE();
  135.     uint16_t inputs = 0;
  136.  
  137.     /* Read input registers from device */
  138.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  139.     messageBuf[1] = PCA95xx_REG_INPUT0;
  140.     TWI_Start_Read_Write( messageBuf, 2 );
  141.     while ( TWI_Transceiver_Busy() );
  142.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  143.     TWI_Start_Read_Write( messageBuf, 3 );
  144.     while ( TWI_Transceiver_Busy() );
  145.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  146.     {
  147.         inputs = (messageBuf[2]<<8)|messageBuf[1];
  148.     }
  149.    
  150.     PCA_INT_ENABLE();
  151.     return inputs;
  152. }
  153.  
  154. /*---------------------------------------------------------------------------*/
  155.  
  156. void Pca95xx_SetOutputs(uint16_t outputs, uint16_t mask)
  157. {
  158.     unsigned char messageBuf[5];
  159.  
  160.     /* Disable interrupts while tampering with the global vars */
  161.     uint8_t sreg = SREG;
  162.     cli();
  163.    
  164.     /* Set masked ones in outputs to global var */
  165.     Pca95xx_outputs |= (outputs&mask);
  166.     /* Clear masked zeros in outputs to global var */
  167.     Pca95xx_outputs &= (outputs|(~mask));
  168.     /* Set output registers */
  169.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  170.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  171.     messageBuf[2] = outputs&0xff;
  172.     messageBuf[3] = (outputs>>8)&0xff;
  173.     TWI_Start_Read_Write( messageBuf, 4 );
  174.     while ( TWI_Transceiver_Busy() );
  175.  
  176.     SREG = sreg;
  177. }
  178.  
  179. /*---------------------------------------------------------------------------*/
  180.  
  181. void Pca95xx_SetDirection(uint16_t direction, uint16_t mask)
  182. {
  183.     unsigned char messageBuf[5];
  184.  
  185.     /* Disable interrupts while tampering with the global vars */
  186.     uint8_t sreg = SREG;
  187.     cli();
  188.  
  189.     /* Set masked ones in direction to global var */
  190.     Pca95xx_direction |= (direction&mask);
  191.     /* Clear masked zeros in direction to global var */
  192.     Pca95xx_direction &= (direction|(~mask));
  193.     /* Set direction registers */
  194.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  195.     messageBuf[1] = PCA95xx_REG_CONF0;
  196.     messageBuf[2] = direction&0xff;
  197.     messageBuf[3] = (direction>>8)&0xff;
  198.     TWI_Start_Read_Write( messageBuf, 4 );
  199.     while ( TWI_Transceiver_Busy() );
  200.     SREG = sreg;
  201. }
  202.