Subversion Repositories HomeAutomation

Rev

Rev 1500 | Rev 1513 | 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.     /* Store address */
  60.     Pca95xx_address = (PCA95xx_I2C_DEV_ADDR|(address&7));
  61.     //printf("i0x%04X\n", Pca95xx_address);
  62.    
  63.     /* Set up interrupt */
  64. #if PCA95XX_NUM_CALLBACKS > 0
  65. #if PCA_INT_VECTOR==INT0_vect
  66.     PORTD|=(1<<PORT2);  /* setup pullup */
  67. #else
  68.     PORTD|=(1<<PORT3);  /* setup pullup */
  69. #endif
  70. #endif
  71.     /* Set up ports? */
  72.     TWI_Master_Initialise();
  73.  
  74.     /* Read output registers from device to global var */
  75.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  76.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  77.     TWI_Start_Read_Write( messageBuf, 2 );
  78.     while ( TWI_Transceiver_Busy() );
  79.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  80.     TWI_Start_Read_Write( messageBuf, 3 );
  81.     while ( TWI_Transceiver_Busy() );
  82.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  83.     {
  84.         /* Disable interrupts while tampering with the global vars */
  85.         uint8_t sreg = SREG;
  86.         cli();
  87.         Pca95xx_outputs = (messageBuf[2]<<8)|messageBuf[1];
  88.         SREG = sreg;
  89.         //printf("o0x%04X\n", Pca95xx_outputs);
  90.     }
  91.  
  92.     /* Read direction registers from device to global var */
  93.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  94.     messageBuf[1] = PCA95xx_REG_CONF0;
  95.     TWI_Start_Read_Write( messageBuf, 2 );
  96.     while ( TWI_Transceiver_Busy() );
  97.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  98.     TWI_Start_Read_Write( messageBuf, 3 );
  99.     while ( TWI_Transceiver_Busy() );
  100.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  101.     {
  102.         /* Disable interrupts while tampering with the global vars */
  103.         uint8_t sreg = SREG;
  104.         cli();
  105.         Pca95xx_direction = (messageBuf[2]<<8)|messageBuf[1];
  106.         SREG = sreg;
  107.         //printf("d0x%04X\n", Pca95xx_direction);
  108.     }
  109.  
  110.     /* Enable interrupt */
  111. #if PCA95XX_NUM_CALLBACKS > 0
  112.     PCA_INT_ENABLE();
  113. #endif
  114. }
  115.  
  116. /*---------------------------------------------------------------------------*/
  117.  
  118. #if PCA95XX_NUM_CALLBACKS > 0
  119. void Pca95xx_SetCallback(uint8_t index, pca95xxCallback_t callback)
  120. {
  121.     /* Disable interrupts while tampering with the global vars */
  122.     uint8_t sreg = SREG;
  123.     cli();
  124.  
  125.     if (index < PCA95XX_NUM_CALLBACKS)
  126.     {
  127.         /* Store the callback */
  128.         Pca95xx_callback[index] = callback;
  129.     }
  130.  
  131.     SREG = sreg;
  132. }
  133. #endif
  134.  
  135. /*---------------------------------------------------------------------------*/
  136.  
  137. uint16_t Pca95xx_GetInputs(void)
  138. {
  139.     unsigned char messageBuf[5];
  140.  
  141.     /* Disable device interrupts while communicating with the device */
  142. #if PCA95XX_NUM_CALLBACKS > 0
  143.     PCA_INT_DISABLE();
  144. #endif
  145.     uint16_t inputs = 0;
  146.  
  147.     /* Read input registers from device */
  148.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  149.     messageBuf[1] = PCA95xx_REG_INPUT0;
  150.     TWI_Start_Read_Write( messageBuf, 2 );
  151.     while ( TWI_Transceiver_Busy() );
  152.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT);
  153.     TWI_Start_Read_Write( messageBuf, 3 );
  154.     while ( TWI_Transceiver_Busy() );
  155.     if (TWI_Read_Data_From_Buffer(messageBuf, 3) == TRUE)
  156.     {
  157.         inputs = (messageBuf[2]<<8)|messageBuf[1];
  158.         //printf("i0x%04X\n", inputs);
  159.     }
  160.    
  161. #if PCA95XX_NUM_CALLBACKS > 0
  162.     PCA_INT_ENABLE();
  163. #endif
  164.     return inputs;
  165. }
  166.  
  167. /*---------------------------------------------------------------------------*/
  168.  
  169. void Pca95xx_SetOutputs(uint16_t outputs, uint16_t mask)
  170. {
  171.     unsigned char messageBuf[5];
  172.  
  173.     /* Disable interrupts while tampering with the global vars */
  174. //  uint8_t sreg = SREG;
  175. //  cli();
  176.  
  177.     /* Set masked ones in outputs to global var */
  178.     Pca95xx_outputs |= (outputs&mask);
  179.     /* Clear masked zeros in outputs to global var */
  180.     Pca95xx_outputs &= (outputs|(~mask));
  181.     /* Set output registers */
  182.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  183.     messageBuf[1] = PCA95xx_REG_OUTPUT0;
  184.     messageBuf[2] = Pca95xx_outputs&0xff;
  185.     messageBuf[3] = (Pca95xx_outputs>>8)&0xff;
  186.     TWI_Start_Read_Write( messageBuf, 4 );
  187.     while ( TWI_Transceiver_Busy() );
  188.  
  189. //  SREG = sreg;
  190. }
  191.  
  192. /*---------------------------------------------------------------------------*/
  193.  
  194. void Pca95xx_SetDirection(uint16_t direction, uint16_t mask)
  195. {
  196.     unsigned char messageBuf[5];
  197.  
  198.     /* Disable interrupts while tampering with the global vars */
  199. //  uint8_t sreg = SREG;
  200. //  cli();
  201.  
  202.     /* Set masked ones in direction to global var */
  203.     Pca95xx_direction |= (direction&mask);
  204.     /* Clear masked zeros in direction to global var */
  205.     Pca95xx_direction &= (direction|(~mask));
  206.     /* Set direction registers */
  207.     messageBuf[0] = (Pca95xx_address<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
  208.     messageBuf[1] = PCA95xx_REG_CONF0;
  209.     messageBuf[2] = Pca95xx_direction&0xff;
  210.     messageBuf[3] = (Pca95xx_direction>>8)&0xff;
  211.     TWI_Start_Read_Write( messageBuf, 4 );
  212.     while ( TWI_Transceiver_Busy() );
  213. //  SREG = sreg;
  214. }
  215.  
  216.  
  217.  
  218. /* GPIO.H interface */
  219.  
  220. /* Port output functions */
  221. void Pca95xx_set_pin(uint8_t nr)
  222. {
  223.     Pca95xx_SetOutputs(1<<nr, 1<<nr);
  224. }
  225.  
  226. void Pca95xx_clr_pin(uint8_t nr)
  227. {
  228.     Pca95xx_SetOutputs(0<<nr, 1<<nr);
  229. }
  230.  
  231. void Pca95xx_set_statement(uint8_t statement, uint8_t nr)
  232. {
  233.     Pca95xx_SetOutputs(statement<<nr, 1<<nr);
  234. }
  235.  
  236. void Pca95xx_toggle_pin(uint8_t nr)
  237. {
  238.     Pca95xx_SetOutputs(Pca95xx_outputs^(1<<nr), 1<<nr);
  239. }
  240.  
  241. uint8_t Pca95xx_get_output_state(uint8_t nr)
  242. {
  243.     return ((Pca95xx_outputs>>nr)&0x1);
  244. }
  245.  
  246.  
  247. /* Port input functions */
  248. uint8_t Pca95xx_get_state(uint8_t nr)
  249. {
  250.     return ((Pca95xx_GetInputs()>>nr)&0x1);
  251. }
  252.  
  253.  
  254. /* Direction functions */
  255. void Pca95xx_set_in(uint8_t nr)
  256. {
  257.     Pca95xx_SetDirection(PCA95xx_CONF_INPUT<<nr, 1<<nr);
  258. }
  259.  
  260. void Pca95xx_set_out(uint8_t nr)
  261. {
  262.     Pca95xx_SetDirection(PCA95xx_CONF_OUTPUT<<nr, 1<<nr);
  263. }
  264.  
  265. uint8_t Pca95xx_get_direction(uint8_t nr)
  266. {
  267.     return ((Pca95xx_direction>>nr)&0x1);
  268. }
  269.  
  270.  
  271.