Subversion Repositories HomeAutomation

Rev

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