Subversion Repositories HomeAutomation

Rev

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