#ifndef ds1620H
#define ds1620H

// handling the DS1620 temperature sensor
template<class Interface> class DS1620 : public Interface
{
        u08  readCfg () { return readCmd8 ( 0xac ); };
        void writeCfg( u08 data ) { writeCmd8(0x0c, data ); };
        u08 readCmd8  ( u08 cmd );
        u16 readCmd16 ( u08 cmd );
        void writeCmd ( u08 cmd ) ;
        void writeCmd8( u08 cmd, u08 data) ;

        void w8( u08 data );
        u08  r8( );
        void shortdelay() { _delay_loop_1(20);};
    public:
        DS1620( );
        s16 readTemp()    { return readCmd16( 0xaa ); };
        s08 readTemp8()   { return readCmd16( 0xaa ) >> 1; };
        void stop()       { writeCmd( 0x22 ); };
        void start()      { writeCmd( 0xee ); };
};

template<class Interface>
void DS1620<Interface>::w8( u08 data )
{
    for ( u08 i = 0; i < 8; ++i ) {
        setCLK( false );
        setDQ( data & 1 );
        data >>= 1;
        shortdelay();
        setCLK( true );
        shortdelay();
    }
}



template<class Interface>
u08 DS1620<Interface>::r8( )
{
    u08 res = 0;
    for ( u08 i = 8; i > 0; --i ) {
        res >>= 1;
        setCLK( false );
        if ( getDQ() )
            res |= 0x80;
        shortdelay();
        setCLK( true );
        shortdelay();
    }
    return res;
}


template<class Interface>
u08 DS1620<Interface>::readCmd8 ( u08 cmd )
{
    setRST( true );
    w8( cmd );
    setReadModeDQ( true );
    u08 res = r8();
    setRST( false );
    setReadModeDQ( false );
    return res;
}

template<class Interface>
u16 DS1620<Interface>::readCmd16 ( u08 cmd )
{
    setRST ( true );
    w8( cmd );
    setReadModeDQ( true );
    u16 res = r8();
    res |= u16(r8()) << 8;
    setRST ( false );
    setReadModeDQ( false );
    return res;
}


template<class Interface>
void DS1620<Interface>::writeCmd (  u08 cmd )
{
    setRST ( true );
    w8( cmd );
    setRST ( false );
}

template<class Interface>
void DS1620<Interface>::writeCmd8 ( u08 cmd, u08 data )
{
    setRST ( true );
    w8( cmd );
    w8( data );
    setRST ( false );
}

template<class Interface>
DS1620<Interface>::DS1620( )
{
    while ( (readCfg() & 0x0f) != 0x0a) {
        writeCfg ( 2 );
        while ( readCfg() & 0x10 );
    }
    start();
    while ( !readTemp8());
}

#endif