Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

LOW_devDS2406.h

Go to the documentation of this file.
00001 /***************************************************************************
00002                           LOW_devDS2406.h  -  description
00003                              -------------------
00004     begin                : Fri Aug 23 2002
00005     copyright            : (C) 2002 by Harald Roelle, Helmut Reiser
00006     email                : roelle@informatik.uni-muenchen.de, reiser@informatik.uni-muenchen.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef LOW_DEVDS2406_H
00019 #define LOW_DEVDS2406_H
00020 
00021 
00022 
00023 #include "LOW_device.h"
00024 
00025 
00026 
00027 /** Device class for DS2406 Dual Addressable Switch Plus 1 kbit Memory.
00028 
00029     DS2406 features:
00030 
00031    - Open drain PIO pins are controlled and their logic level can be determined
00032      over 1-Wire bus for closed-loop control
00033    - Replaces and is fully compatible with DS2407 but no user-programmable
00034      power-on settings and no Hidden Mode
00035    - PIO channel A sink capability of 50mA at 0.4V with soft turn-on; channel B 8mA at 0.4V
00036    - Maximum operating voltage of 13V at PIO-A, 6.5V at PIO-B
00037    - 1024 bits user-programmable OTP EPROM
00038    - User-programmable status memory to control the device
00039    - Multiple DS2406 can be identified on a common 1-Wire bus and be turned on or off
00040      independently of other devices on the bus
00041    - Unique, factory-lasered and tested 64-bit registration number (8-bit family code + 48-bit
00042      serial number + 8-bit CRC tester) assures error-free selection and absolute identity
00043      because no two parts are alike
00044    - On-chip CRC16 generator allows detection of data transfer errors
00045    - Built-in multidrop controller ensures compatibility with other 1-Wire net products
00046    - Reduces control, address, data, programming and power to a single data pin
00047    - Directly connects to a single port pin of a microprocessor and communicates
00048      at up to 16.3 kbits/s
00049    - Supports Conditional Search with userselectable condition
00050    - Vcc bondout for optional external supply to the device (TSOC package only)
00051    - 1-Wire communication operates over a wide voltage range of 2.8V to 6.0V from -40°C to +85°C
00052    - Low cost TO-92 or 6-pin TSOC surface mount package
00053 
00054    @author Harald Roelle, Helmut Reiser
00055  */
00056 class LOW_devDS2406 : public LOW_device  {
00057 
00058 //=======================================================================================
00059 public: 
00060 
00061   //=====================================================================================
00062   //
00063   // exceptions
00064   //
00065 
00066   /** Exception base class for all exceptions thrown by LOW_devDS2406. */
00067   class_DERIVE_FROM_EXCEPTION( devDS2406_error ,LOW_exception);
00068 
00069 
00070 
00071   //=====================================================================================
00072   //
00073   // constants
00074   //
00075   
00076   /** Family code of this specific device. */
00077   static const LOW_deviceIDRaw::devFamCode_t  familyCode = 0x12;
00078 
00079   /** Family name of this specific device. */
00080   static const string familyName;
00081   
00082   static const owCommand_t  ReadMemory_COMMAND         = 0xf0; /**< 1-Wire command byte constant */
00083   static const owCommand_t  ExtendedReadMemory_COMMAND = 0xa5; /**< 1-Wire command byte constant */
00084   static const owCommand_t  WriteMemory_COMMAND        = 0x0f; /**< 1-Wire command byte constant */
00085   static const owCommand_t  WriteStatus_COMMAND        = 0x55; /**< 1-Wire command byte constant */
00086   static const owCommand_t  ReadStatus_COMMAND         = 0xaa; /**< 1-Wire command byte constant */
00087   static const owCommand_t  ChannelAccess_COMMAND      = 0xf5; /**< 1-Wire command byte constant */
00088 
00089 
00090   
00091   //=====================================================================================
00092   //
00093   // type definitions
00094   //
00095   
00096   typedef std::vector<LOW_devDS2406*> devDS2406PtrVec_t;    /**< Vector type of class device pointers. */
00097 
00098   /** Type for PIO channel selection. */
00099   typedef enum { noneSelect=0, chanASelect=1, chanBSelect=2, chanBothSelect=3}  chanSelect_t;
00100 
00101   /** Type for search source selection. */
00102   typedef enum { latchSelect=1, flipFlopSelect=2, curStatusSelect=3}            sourceSelect_t;
00103 
00104   /** Type for PIO transistor states. */
00105   typedef enum { pioTransistorOn=0, pioTransistorOff=1}                         pioTransistor_t;
00106 
00107   /** Type for activity polarity selection. */
00108   typedef enum { activeLow=0, activeHigh=1}                                     activePolarity_t;
00109 
00110   /** DS2406 internal status register as defined by Dallas. */
00111   typedef struct statusRegister_t {
00112     activePolarity_t   activePolarity;
00113     sourceSelect_t     sourceSelect;
00114     chanSelect_t       channelSelect;
00115     pioTransistor_t    channelFFQ_pioA;
00116     pioTransistor_t    channelFFQ_pioB;
00117     bool               isExternalPowered;   // bit 7
00118   } statusRegister_t;
00119 
00120     
00121   //=====================================================================================
00122   //
00123   // classes
00124   //
00125 
00126 
00127   /** Class for accessing the PIO channels.
00128   
00129       The Channel Access command is used to access the PIO channels to sense the logical status
00130       of the output node and the output transistor and to change the status of the output transistor.
00131 
00132       As there are many combinations of reading/writing the command is implemented as a class.
00133       The programmer himself is responsible to match read/write cycles according to prior selected
00134       options on instance creation.
00135 
00136       For details see the original Dallas documentation.
00137 
00138       <B>Note:</B> As any other command creating an instance of this class locks the device.
00139                    Remember to destroy the object to release the device.
00140    */
00141   class cmd_ChannelAccess : public linkLock {
00142 
00143   //-------------------------------------------------------------------------------------
00144   public:
00145     
00146     //-------------------------------------------------------------------------------------
00147     // type definitions
00148     //
00149 
00150     /** Type for CRC cycle selection. */
00151     typedef enum { CRC_disable=0, CRC_after1Byte=1, CRC_after8Byte=2, CRC_after32Byte=3} CRCtype_t;
00152 
00153     /** Type for interleave mode selection. */
00154     typedef enum { asyncInterleaveMode=0, syncInterleaveMode=1 }                         interleaveMode_t;
00155 
00156     /** Type for toggle mode selection. */
00157     typedef enum { noToggleMode=0, toggleMode=1}                                         toggleMode_t;
00158 
00159     /** Type for inition I/O mode selection. */
00160     typedef enum { writeMode=0, readMode=1}                                              initialMode_t;
00161 
00162     /** Type for latch reset selection. */
00163     typedef enum { noResetLatches=0, resetLatches=1}                                     activityLatchReset_t;
00164 
00165     /** DS2406 channel info as defined by Dallas. */
00166     typedef struct channelInfo_t {
00167       bool channelFFQ_pioA;     // bit 0
00168       bool channelFFQ_pioB;
00169       bool sensedLevel_pioA;
00170       bool sensedLevel_pioB;
00171       bool activityLatch_pioA;
00172       bool activityLatch_pioB;
00173       bool hasPioB;
00174       bool isExternalPowered;   // bit 7
00175     } channelInfo_t;
00176   
00177     //-------------------------------------------------------------------------------------
00178     // constructors
00179     //
00180 
00181     /** Constructor with specification of command options.
00182         Obtains a lock on the device.
00183         
00184         @param  inDevice           Reference to the device the command operates on.
00185         @param  inCRCtype          CRC cycle selection.
00186         @param  inChanSelect       PIO channel selection.
00187         @param  inInterleaveMode   Interleave mode selection.
00188         @param  inToggleMode       Toggle mode selection.
00189         @param  inInitialMode      Initial I/O mode selection.
00190         @param  inALR              Latch reset selection.
00191 
00192         @throw devDS2406_error  Thrown when illegal combination of modes is selected.
00193      */
00194     cmd_ChannelAccess( const LOW_devDS2406 &inDevice,
00195                        const CRCtype_t inCRCtype, const chanSelect_t inChanSelect, 
00196                        const interleaveMode_t inInterleaveMode, const toggleMode_t inToggleMode, 
00197                        const initialMode_t inInitialMode, const activityLatchReset_t inALR);
00198 
00199     /** Destructor.
00200         Releases the lock on the device.
00201      */
00202     ~cmd_ChannelAccess();
00203     
00204     //-------------------------------------------------------------------------------------
00205     // methods
00206     //
00207 
00208     /** Get the channel info read after sending command.
00209      */
00210     channelInfo_t& getChannelInfo();
00211 
00212     /** Receive 1 bit from the device.
00213         @return  Bit that was reveived.
00214      */
00215     bool readDataBit() const;
00216 
00217     /** Receive 1 byte from the device.
00218         @return  Byte that was reveived.
00219      */
00220     uint8_t readDataByte() const;
00221 
00222     /** Receive a block of bytes from the device.
00223       @param  outBytes   Values that were reveived. Read length is determined
00224                          by the preset length of the vector.
00225      */
00226     void readData( byteVec_t &outBytes) const;
00227 
00228     /** Send 1 bit to the device.
00229         @param   inSendBit   Bit to send.
00230      */
00231     void writeData( const bool inSendBit) const;
00232 
00233     /** Send 1 byte to the device.
00234         @param   inSendByte  Byte to send.
00235      */
00236     void writeData( const uint8_t inSendByte) const;
00237 
00238     /** Send block of bytes to the device.
00239         @param  inSendBytes  Block of bytes to send.
00240      */
00241     void writeData( const byteVec_t &inSendBytes) const;
00242   
00243   //-------------------------------------------------------------------------------------
00244   private:
00245     const LOW_devDS2406  &device;      /**< Device the command is operating on */
00246     channelInfo_t        channelInfo;  /**< Channel info received after issuing the command */
00247     
00248   };
00249   
00250   
00251   //=====================================================================================
00252   //
00253   // constructors
00254   //
00255   
00256   /** Real constructor corresponding to static pseudo constructor new_Instance().
00257       @param  inSegment  Reference to network segment the device is on.
00258       @param  inDevID    Reference to device's ID.
00259    */
00260   LOW_devDS2406( LOW_netSegment &inSegment, const LOW_deviceID &inDevID);
00261 
00262   /** Destructor.
00263    */
00264   ~LOW_devDS2406();
00265 
00266   
00267   //=====================================================================================
00268   //
00269   // methods
00270   //
00271 
00272   /** Get the device's family name.
00273       @return Family name of the device.
00274    */
00275   virtual string getFamilyName() const { return familyName; };
00276 
00277   
00278   /** Get wether the device is externally powered.
00279       @return  Boolean indicates external power.
00280    */
00281   bool getIsExternalPowered() const;
00282 
00283   
00284   /** Get wether the second PIO channel is present.
00285       @return  Boolean indicates presence of channel B.
00286    */
00287   bool getHasPioB() const;
00288 
00289   
00290   /** Get the current search condition.
00291       See also setSearchCondition().
00292 
00293       @param  outStatusRegister  Pointer to status register struture. Results
00294                                  are filled in there.
00295    */
00296   void getSearchCondition( LOW_devDS2406::statusRegister_t *outStatusRegister) const;
00297 
00298     
00299   /** Set the search condition and status of the PIO transistors.
00300   
00301       The condition is specified by the bit functions CSS0 to CSS4 in Status Memory location 7.
00302       At power-on all these bits are 1s. As long as the device remains powered up, the
00303       modified search conditions are available for use at any time.
00304       For the conditional search, one can specify
00305         - the polarity (HIGH or LOW; CSS0)
00306         - the source (PIO-pin, channel flip flop or activity latch; CSS1, CSS2)
00307         - the channel of interest (A, B or the logical OR of A, B; CSS3, CSS4)
00308 
00309       The table shows all qualifying conditions and the required settings for CSS0 to CSS4:
00310       <pre>
00311               DESCRIPTION        |   CONDITIONAL SEARCH SELECT CODE
00312       -----------------+---------+--------------+-------------+---------
00313                        |         |CHANNEL SELECT|SOURCE SELECT|POLARITY
00314                        |         +------+-------+------+------+---------
00315        CONDITION       | CHANNEL | CSS4 | CSS3  | CSS2 | CSS1 | CSS0
00316       =================+=========+======+=======+======+======+=========
00317       RESERVED         |         |  Don't care  | 0    | 0    | 0/1
00318       -----------------+---------+------+-------+------+------+---------
00319       Unconditional    |neither  | 0    | 0     | At least one| 0
00320                        |         |      |       | must be 1   |
00321       -----------------+---------+------+-------+------+------+---------
00322       Activity Latch=0 | A       | 0    | 1     | 0    | 1    | 0
00323       -----------------+---------+------+-------+------+------+---------
00324       Activity Latch=1 | A       | 0    | 1     | 0    | 1    | 1
00325       -----------------+---------+------+-------+------+------+---------
00326       Channel FF = 0   | A       | 0    | 1     | 1    | 0    | 0
00327       (transistor on)  |         |      |       |      |      |
00328       -----------------+---------+------+-------+------+------+---------
00329       Channel FF = 1   | A       | 0    | 1     | 1    | 0    | 1
00330       (transistor off) |         |      |       |      |      |
00331       -----------------+---------+------+-------+------+------+---------
00332       PIO Low          | A       | 0    | 1     | 1    | 1    | 0
00333       -----------------+---------+------+-------+------+------+---------
00334       PIO High         | A       | 0    | 1     | 1    | 1    | 1
00335       -----------------+---------+------+-------+------+------+---------
00336       Activity Latch=0 | B       | 1    | 0     | 0    | 1    | 0
00337       -----------------+---------+------+-------+------+------+---------
00338       Activity Latch=1 | B       | 1    | 0     | 0    | 1    | 1
00339       -----------------+---------+------+-------+------+------+---------
00340       Channel FF = 0   | B       | 1    | 0     | 1    | 0    | 0
00341       (transistor on)  |         |      |       |      |      |
00342       -----------------+---------+------+-------+------+------+---------
00343       Channel FF = 1   | B       | 1    | 0     | 1    | 0    | 1
00344       (transistor off) |         |      |       |      |      |
00345       -----------------+---------+------+-------+------+------+---------
00346       PIO Low          | B       | 1    | 0     | 1    | 1    | 0
00347       -----------------+---------+------+-------+------+------+---------
00348       PIO High         | B       | 1    | 0     | 1    | 1    | 1
00349       -----------------+---------+------+-------+------+------+---------
00350       Activity Latch=0 | A or B  | 1    | 1     | 0    | 1    | 0
00351       -----------------+---------+------+-------+------+------+---------
00352       Activity Latch=1 | A or B  | 1    | 1     | 0    | 1    | 1
00353       -----------------+---------+------+-------+------+------+---------
00354       Channel FF = 0   | A or B  | 1    | 1     | 1    | 0    | 0
00355       (transistor on)  |         |      |       |      |      |
00356       -----------------+---------+------+-------+------+------+---------
00357       Channel FF = 1   | A or B  | 1    | 1     | 1    | 0    | 1
00358       (transistor off) |         |      |       |      |      |
00359       -----------------+---------+------+-------+------+------+---------
00360       PIO Low          | A or B  | 1    | 1     | 1    | 1    | 0
00361       -----------------+---------+------+-------+------+------+---------
00362       PIO High         | A or B  | 1    | 1     | 1    | 1    | 1
00363       -----------------+---------+------+-------+------+------+---------
00364       </pre>
00365 
00366       @param inChanSelect      Select channel search condition.
00367       @param inSourceSelect    Select source search condition.
00368       @param inPolaritySelect  Select polarity search condition.
00369       @param inPioATrans       Status of PIO transistor A.
00370       @param inPioBTrans       Status of PIO transistor B.
00371 
00372       @throw devDS2406_error  Thrown when channel B is selected without being present.
00373    */
00374   void setSearchCondition( const chanSelect_t inChanSelect, const sourceSelect_t inSourceSelect, 
00375                            const activePolarity_t inPolaritySelect,
00376                            const pioTransistor_t inPioATrans, const pioTransistor_t inPioBTrans) const;
00377 
00378 
00379   /** Read from EPROM memory.
00380   
00381       The Read Memory command is used to read data from the 1024-bit EPROM data memory field.
00382       The bus master follows the command byte with a two-byte address (TA1=(T7:T0), TA2=(T15:T8))
00383       that indicates a starting byte location within the data field. With every subsequent read
00384       data time slot the bus master receives data from the DS2406 starting at the initial address
00385       and continuing until the end of the 1024-bits data field is reached or until a Reset Pulse
00386       is issued.
00387 
00388       If reading occurs through the end of memory space, the bus master issues sixteen additional
00389       read time slots and the DS2406 will respond with a 16-bit CRC of the command, address bytes
00390       and all data bytes read from the initial starting byte through the last byte of memory.
00391       This CRC is the result of clearing the CRC generator and then shifting in the command byte
00392       followed by the two address bytes and the data bytes beginning at the first addressed memory
00393       location and continuing through to the last byte of the EPROM data
00394       memory. Any reads ended by a Reset Pulse prior to reaching the end of memory will not have
00395       the 16-bit CRC available.
00396 
00397       Typically the software controlling the device should store a 16-bit CRC with each page
00398       of data to insure rapid, error-free data transfers that eliminate having to read a page
00399       multiple times to determine if the received data is correct or not. (See Book of DS19xx
00400       iButton Standards, Chapter 7 for the recommended file structure to be used with the 1-Wire
00401       environment). If CRC values are imbedded within the data it is unnecessary to read the
00402       end-of-memory CRC. The Read Memory command can be ended at any point by issuing a Reset Pulse.
00403 
00404       @param  inStartAddr  Start address for reading.
00405       @param  outBytes     Values that were reveived. Read length is determined
00406                            by the preset length of the vector.
00407    */
00408   void cmd_ReadMemory( const uint8_t inStartAddr, byteVec_t &outBytes) const;
00409 
00410   
00411   //cmd_ExtendedReadMemory();  // Not implemented yet
00412 
00413   
00414   //cmd_WriteMemory();         // Not implemented yet
00415 
00416   
00417   /** Read from status memory.
00418   
00419       The Read Status command is used to read data from the Status Memory field. The functional flow
00420       of this command is identical to the Read Memory command. Since the Status Memory is only 8 bytes,
00421       the DS2406 will send the 16-bit CRC after the last byte of status information has been transmitted.
00422 
00423       DS2406 status memory map:
00424       <pre>
00425       ADDRESS   | BIT 7             | BIT 6         | BIT 5         | BIT 4        | BIT 3        | BIT 2       | BIT 1       | BIT 0
00426       ==========+===================+===============+===============+==============+==============+=============+=============+==========
00427       0 (EPROM) | BM3               | BM2           | BM1           | BM0          | WP3          | WP2         | WP1         | WP0
00428       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00429       1 (EPROM) | 1                 | 1             | 1             | 1            | 1            | 1           | Redir. 0    | Redir. 0
00430       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00431       2 (EPROM) | 1                 | 1             | 1             | 1            | 1            | 1           | Redir. 1    | Redir. 1
00432       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00433       3 (EPROM) | 1                 | 1             | 1             | 1            | 1            | 1           | Redir. 2    | Redir. 2
00434       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00435       4 (EPROM) | 1                 | 1             | 1             | 1            | 1            | 1           | Redir. 3    | Redir. 3
00436       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00437       5 (EPROM) |                                                   EPROM Factory Test byte
00438       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00439       6 (EPROM) |                                                 Don t care, always reads 00
00440       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00441       7 (SRAM)  | Supply Indication | PIO-B Channel | PIO-A Channel | CSS4 Channel | CSS3 Channel | CSS2 Source | CSS1 Source | CSS0
00442                 | (read only)       | Flip-flop     | Flip-flop     |      Select  |      Select  |      Select |      Select | Polarity
00443       ----------+-------------------+---------------+---------------+--------------+--------------+-------------+-------------+----------
00444       </pre>
00445 
00446       @param  inStartAddr  Start address for reading.
00447       @param  outBytes     Values that were reveived. Read length is determined
00448                            by the preset length of the vector.
00449 
00450       @throw devDS2406_error  Thrown when illegal address is selected.
00451    */  
00452   void cmd_ReadStatus( const uint8_t inStartAddr, byteVec_t &outBytes) const;
00453 
00454    
00455   /** Write to status memory.
00456   
00457       The Write Status command is used to program the Status Memory, which includes the
00458       specification of the Conditional Search Settings.
00459 
00460       The Status Memory address range is
00461       0000h to 0007h. The general programming algorithm is valid for the EPROM section of
00462       the Status Memory (addresses 0 to 4) only. The Status memory locations 5 and 6 are
00463       already pre-programmed to 00h and therefore cannot be altered. Status memory
00464       location 7 consists of static RAM, which can be reprogrammed without limitation.
00465       The supply indication (bit 7) is read-only; attempts to write to it are ignored. The
00466       function flow for writing to status memory location 7 is basically the same as for
00467       the other EPROM Status Memory Bytes. However, instead of a programming pulse the bus
00468       master sends a FFh byte (equivalent to 8 Write-One Time Slots) to transfer the new
00469       value from the scratchpad to the status memory.
00470 
00471       See also cmd_ReadStatus().
00472 
00473       @param  inStartAddr    Start address for reading.
00474       @param  inWriteBytes   Values to write.
00475 
00476       @throw devDS2406_error  Thrown when illegal address is selected.
00477    */
00478   void cmd_WriteStatus( const uint8_t inStartAddr, const byteVec_t &inWriteBytes) const;
00479     
00480 
00481     
00482 //=======================================================================================
00483 protected:
00484 
00485   //=====================================================================================
00486   //
00487   // friends
00488   //
00489   
00490   friend class cmd_ChannelAccess;  /**< required for accessing the device's lock */
00491   
00492   
00493   //=====================================================================================
00494   //
00495   // attributes
00496   //
00497   
00498   bool  isExternalPowered;   /**< External supply indicator */
00499   bool  hasPioB;             /**< Wether the second PIO channel is present */
00500 
00501     
00502   //=====================================================================================
00503   //
00504   // static methods
00505   //
00506   
00507   /** Static pseudo constructor for registering with LOW_deviceFactory.
00508       @param  inSegment  Reference to network segment the device is on.
00509       @param  inDevID    Reference to device's ID.
00510       @return  New dynamic instance of specific device class.
00511    */
00512   static LOW_device* new_Instance( LOW_netSegment &inNetSegment, const LOW_deviceID &inDevID);
00513 
00514   
00515   //=====================================================================================
00516   //
00517   // methods
00518   //
00519   
00520   /** Universal, internal data reading.
00521       Implements common parts of memory reading.
00522   
00523       @param  inStartAddr  Start address for reading.
00524       @param  outBytes     Values that were reveived. Read length is determined
00525                            by the preset length of the vector.
00526       @param  inMaxLen     Maximum readable memory size.
00527       @param  inCommand    1-Wire command to start the read cycle.
00528 
00529       @throw devDS2406_error  Thrown when illegal address is selected.
00530    */
00531   void readMemUniversal( const uint16_t inStartAddr, byteVec_t &outBytes, 
00532                          const uint16_t inMaxLen, const owCommand_t inCommand) const;
00533   
00534   
00535   
00536 //=======================================================================================
00537 private:
00538 
00539   //=====================================================================================
00540   //
00541   // static initializer
00542   //
00543   
00544   /** Needed for dirty little C++ hack to force static initialization on application start.
00545       @see initialize()
00546   */
00547   static int initHelper;
00548 
00549   /** Static inizializer to register the class with LOW_deviceFactory.
00550       @see initHelper
00551   */
00552   static int initialize();
00553   
00554 };
00555 
00556 #endif

Generated on Sun Jan 12 21:07:43 2003 by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001