Subversion Repositories HomeAutomation

Rev

Rev 1485 | Rev 1495 | 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 PCA95XX_NUM_CALLBACKS > 0
  68. #if PCA_INT_VECTOR==INT0_vect
  69.     PORTD|=(1<<PORT2);  /* setup pullup */
  70. #else
  71.     PORTD|=(1<<PORT3);  /* setup pullup */
  72. #endif
  73. #endif
  74.     /* Set up ports? */
  75.     TWI_Master_Initialise();
  76.    
  77.     /* Read output registers from device to global var */
  78.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  79.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  80.     TWI_Start_Read_Write( messageBuf, 2 );
  81.     while ( TWI_Transceiver_Busy() );
  82.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  83.     TWI_Start_Read_Write( messageBuf, 3 );
  84.     while ( TWI_Transceiver_Busy() );
  85.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  86.     {
  87.         Pca95xx_outputs = (messageBuf[2]<<8)|messageBuf[1];
  88.     }
  89.  
  90.     /* Read direction registers from device to global var */
  91.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  92.     messageBuf[1] = PCA95xx_REG_CONF0;
  93.     TWI_Start_Read_Write( messageBuf, 2 );
  94.     while ( TWI_Transceiver_Busy() );
  95.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  96.     TWI_Start_Read_Write( messageBuf, 3 );
  97.     while ( TWI_Transceiver_Busy() );
  98.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  99.     {
  100.         Pca95xx_direction = (messageBuf[2]<<8)|messageBuf[1];
  101.     }
  102.    
  103.     /* Enable interrupt */
  104. #if PCA95XX_NUM_CALLBACKS > 0
  105.     PCA_INT_ENABLE();
  106. #endif
  107. //  SREG = sreg;
  108. }
  109.  
  110. /*---------------------------------------------------------------------------*/
  111.  
  112. #if PCA95XX_NUM_CALLBACKS > 0
  113. void Pca95xx_SetCallback(uint8_t index, pca95xxCallback_t callback)
  114. {
  115.     /* Disable interrupts while tampering with the global vars */
  116.     uint8_t sreg = SREG;
  117.     cli();
  118.  
  119.     if (index < PCA95XX_NUM_CALLBACKS)
  120.     {
  121.         /* Store the callback */
  122.         Pca95xx_callback[index] = callback;
  123.     }
  124.  
  125.     SREG = sreg;
  126. }
  127. #endif
  128.  
  129. /*---------------------------------------------------------------------------*/
  130.  
  131. uint16_t Pca95xx_GetInputs(void)
  132. {
  133.     unsigned char messageBuf[5];
  134.  
  135.     /* Disable device interrupts while communicating with the device */
  136. #if PCA95XX_NUM_CALLBACKS > 0
  137.     PCA_INT_DISABLE();
  138. #endif
  139.     uint16_t inputs = 0;
  140.  
  141.     /* Read input registers from device */
  142.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  143.     messageBuf[1] = PCA95xx_REG_INPUT0;
  144.     TWI_Start_Read_Write( messageBuf, 2 );
  145.     while ( TWI_Transceiver_Busy() );
  146.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  147.     TWI_Start_Read_Write( messageBuf, 3 );
  148.     while ( TWI_Transceiver_Busy() );
  149.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  150.     {
  151.         inputs = (messageBuf[2]<<8)|messageBuf[1];
  152.     }
  153.    
  154. #if PCA95XX_NUM_CALLBACKS > 0
  155.     PCA_INT_ENABLE();
  156. #endif
  157.     return inputs;
  158. }
  159.  
  160. /*---------------------------------------------------------------------------*/
  161.  
  162. void Pca95xx_SetOutputs(uint16_t outputs, uint16_t mask)
  163. {
  164.     unsigned char messageBuf[5];
  165.  
  166.     /* Disable interrupts while tampering with the global vars */
  167.     uint8_t sreg = SREG;
  168.     cli();
  169.    
  170.     /* Set masked ones in outputs to global var */
  171.     Pca95xx_outputs |= (outputs&mask);
  172.     /* Clear masked zeros in outputs to global var */
  173.     Pca95xx_outputs &= (outputs|(~mask));
  174.     /* Set output registers */
  175.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  176.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  177.     messageBuf[2] = outputs&0xff;
  178.     messageBuf[3] = (outputs>>8)&0xff;
  179.     TWI_Start_Read_Write( messageBuf, 4 );
  180.     while ( TWI_Transceiver_Busy() );
  181.  
  182.     SREG = sreg;
  183. }
  184.  
  185. /*---------------------------------------------------------------------------*/
  186.  
  187. void Pca95xx_SetDirection(uint16_t direction, uint16_t mask)
  188. {
  189.     unsigned char messageBuf[5];
  190.  
  191.     /* Disable interrupts while tampering with the global vars */
  192.     uint8_t sreg = SREG;
  193.     cli();
  194.  
  195.     /* Set masked ones in direction to global var */
  196.     Pca95xx_direction |= (direction&mask);
  197.     /* Clear masked zeros in direction to global var */
  198.     Pca95xx_direction &= (direction|(~mask));
  199.     /* Set direction registers */
  200.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  201.     messageBuf[1] = PCA95xx_REG_CONF0;
  202.     messageBuf[2] = direction&0xff;
  203.     messageBuf[3] = (direction>>8)&0xff;
  204.     TWI_Start_Read_Write( messageBuf, 4 );
  205.     while ( TWI_Transceiver_Busy() );
  206.     SREG = sreg;
  207. }
  208.