Subversion Repositories HomeAutomation

Rev

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