Subversion Repositories HomeAutomation

Rev

Rev 1148 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*        Access Dallas 1-Wire Device with ATMEL AVRs                   */
  4. /*                                                                      */
  5. /*              Author: Peter Dannegger                                 */
  6. /*                      danni@specs.de                                  */
  7. /*                                                                      */
  8. /* modified by Martin Thomas <eversmith@heizung-thomas.de> 9/2004       */
  9. /************************************************************************/
  10.  
  11. #include <avr/io.h>
  12. #include <avr/interrupt.h>
  13.  
  14. #include "delay.h"
  15. #include "onewire.h"
  16.  
  17. #include <config.h>
  18.  
  19. #ifdef OW_ONE_BUS
  20.  
  21. #define OW_GET_IN()   gpio_get_state(OW_PIN)
  22. #define OW_OUT_LOW()  gpio_clr_pin(OW_PIN)
  23. #define OW_OUT_HIGH() gpio_set_pin(OW_PIN)
  24. #define OW_DIR_IN()   gpio_set_in(OW_PIN)
  25. #define OW_DIR_OUT()  gpio_set_out(OW_PIN)
  26.  
  27.  
  28. #else
  29.  
  30. /* set bus-config with ow_set_bus() */
  31. uint8_t OW_PIN_MASK;
  32. volatile uint8_t* OW_IN;
  33. volatile uint8_t* OW_OUT;
  34. volatile uint8_t* OW_DDR;
  35.  
  36. #define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
  37. #define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
  38. #define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
  39. #define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
  40. #define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
  41. //#define OW_PIN2 PD6
  42. //#define OW_DIR_IN2()   ( *OW_DDR &= ~(1 << OW_PIN2 ) )
  43.  
  44. void ow_set_bus(volatile uint8_t* in,
  45.     volatile uint8_t* out,
  46.     volatile uint8_t* ddr,
  47.     uint8_t pin)
  48. {
  49.     OW_DDR=ddr;
  50.     OW_OUT=out;
  51.     OW_IN=in;
  52.     OW_PIN_MASK=(1<<pin);
  53.     ow_reset();
  54. }
  55.  
  56. #endif
  57.  
  58. uint8_t ow_input_pin_state()
  59. {
  60.     return OW_GET_IN();
  61. }
  62.  
  63. void ow_parasite_enable(void)
  64. {
  65.     OW_OUT_HIGH();
  66.     OW_DIR_OUT();
  67. }
  68.  
  69. void ow_parasite_disable(void)
  70. {
  71.     OW_OUT_LOW();
  72.     OW_DIR_IN();
  73. }
  74.  
  75. uint8_t ow_reset(void)
  76. {
  77.     uint8_t err;
  78.     uint8_t sreg;
  79.    
  80.     OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)
  81.     OW_DIR_OUT(); // pull OW-Pin low for 480us
  82.    
  83.     delay_us(480);
  84.    
  85.     sreg=SREG;
  86.     cli();
  87.    
  88.     // set Pin as input - wait for clients to pull low
  89.     OW_DIR_IN(); // input
  90.    
  91.     delay_us(66);
  92.     err = OW_GET_IN();      // no presence detect
  93.     // nobody pulled to low, still high
  94.    
  95.     SREG=sreg; // sei()
  96.    
  97.     // after a delay the clients should release the line
  98.     // and input-pin gets back to high due to pull-up-resistor
  99.     delay_us(480-66);
  100.     if( OW_GET_IN() == 0 )      // short circuit
  101.         err = 1;
  102.    
  103.     return err;
  104. }
  105.  
  106. /* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
  107.    The master should sample at the end of the 15-slot after initiating
  108.    the read-time-slot. The variable bus-settings need more
  109.    cycles than the constant ones so the delays had to be shortened
  110.    to achive a 15uS overall delay
  111.    Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
  112.    but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
  113. uint8_t ow_bit_io( uint8_t b )
  114. {
  115.     uint8_t sreg;
  116.    
  117.     sreg=SREG;
  118.     cli();
  119.    
  120.     OW_DIR_OUT(); // drive bus low
  121.    
  122.     delay_us(1); // Recovery-Time wuffwuff was 1
  123.     if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
  124.        
  125.     // wuffwuff delay was 15uS-1 see comment above
  126.     delay_us(15-1-OW_CONF_DELAYOFFSET);
  127.        
  128.     if( OW_GET_IN() == 0 ) b = 0;  // sample at end of read-timeslot
  129.    
  130.     delay_us(60-15);
  131.     OW_DIR_IN();
  132.    
  133.     SREG=sreg; // sei();
  134.    
  135.     return b;
  136. }
  137.  
  138.  
  139. uint8_t ow_byte_wr( uint8_t b )
  140. {
  141.     uint8_t i = 8, j;
  142.    
  143.     do {
  144.         j = ow_bit_io( b & 1 );
  145.         b >>= 1;
  146.         if( j ) b |= 0x80;
  147.     } while( --i );
  148.    
  149.     return b;
  150. }
  151.  
  152.  
  153. uint8_t ow_byte_rd( void )
  154. {
  155.   // read by sending 0xff (a dontcare?)
  156.   return ow_byte_wr( 0xFF );
  157. }
  158.  
  159.  
  160. uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
  161. {
  162.     uint8_t i, j, next_diff;
  163.     uint8_t b;
  164.    
  165.     if( ow_reset() ) return OW_PRESENCE_ERR;    // error, no device found
  166.    
  167.     ow_byte_wr( OW_SEARCH_ROM );            // ROM search command
  168.     next_diff = OW_LAST_DEVICE;         // unchanged on last device
  169.    
  170.     i = OW_ROMCODE_SIZE * 8;                    // 8 bytes
  171.    
  172.     do {
  173.         j = 8;                  // 8 bits
  174.         do {
  175.             b = ow_bit_io( 1 );         // read bit
  176.             if( ow_bit_io( 1 ) ) {          // read complement bit
  177.                 if( b )                 // 11
  178.                 return OW_DATA_ERR;         // data error
  179.             }
  180.             else {
  181.                 if( !b ) {              // 00 = 2 devices
  182.                     if( diff > i || ((*id & 1) && diff != i) ) {
  183.                     b = 1;              // now 1
  184.                     next_diff = i;          // next pass 0
  185.                     }
  186.                 }
  187.             }
  188.             ow_bit_io( b );                 // write bit
  189.             *id >>= 1;
  190.             if( b ) *id |= 0x80;            // store bit
  191.            
  192.             i--;
  193.            
  194.         } while( --j );
  195.        
  196.         id++;                   // next byte
  197.    
  198.     } while( i );
  199.    
  200.     return next_diff;               // to continue search
  201. }
  202.  
  203.  
  204. void ow_command( uint8_t command, uint8_t *id )
  205. {
  206.     uint8_t i;
  207.  
  208.     ow_reset();
  209.  
  210.     if( id ) {
  211.         ow_byte_wr( OW_MATCH_ROM );         // to a single device
  212.         i = OW_ROMCODE_SIZE;
  213.         do {
  214.             ow_byte_wr( *id );
  215.             id++;
  216.         } while( --i );
  217.     }
  218.     else {
  219.         ow_byte_wr( OW_SKIP_ROM );          // to all devices
  220.     }
  221.    
  222.     ow_byte_wr( command );
  223. }
  224.