' DS1624_1.Bas  (PICAXE-28X)
'
' Configures DS1624 in single shot mode.  Performs ten temperature measurements, displays
' to the terminal  and saves to the DS1624 EEPROM.  Then reads from EEPROM and displays to
' the terminal.  May be modified to implement simple and inexpensive data logger.
'
' This implementation does not use the PICAXE commands to interface with I2C devices.  The
' implementation differs from the bit bang implementation I have used for the PICAXE-18X.
'
' In this implementation, the direction of a pin is implemented by reading TRISC, inverting all
' bits, and then either anding with a 0 (input) or oring with a logic 1 (output) and copying
' this to  DIRSC.  The state of a pin, is implemented by reading PORTC and then either anding
' with a logic 0 (low output) or with a logic 1 (high output).  See routines SDAHigh, SDALow,
' SCLHigh, SCLLow.
'
' This implementation does not include the code to display the temperature in decimal format.
' (Please see my implemtation of a simialr routine for the PICAXE-18X).
'
' PICAXE-18X		          DS1624
'                     +5
'                      |
'                      4.7K
'                      |
' PortC7 (term 18) -------------- SCL (term 2) ---------- To other I2C devices
'
'                      +5
                       |
                       4.7K
                       |
' PortC6 (term 17) -------------- SDA (term 1) ----------
'
' Note that the strapping of A2, A1 and A0 on the DS1624 determine the DevAdr.  This may
' be in the range of 0 to 7.  Note that up to eight DS1624 devices, each having a different
' strapping, may be accommodated on the same two signal leads.
'
' copyright, Peter H Anderson, Baltimore, MD, Aug, '04


Symbol  SDADir0ut = %01000000 ' Pin6
Symbol  SDADirIn = %10111111

Symbol  SCLDirOut = %10000000
Symbol  SCLDirIn  = %01111111

Symbol  SCLState0 = %01111111
Symbol  SCLState1 = %10000000

Symbol  SDAState0 = %10111111
Symbol  SDAState1 = %01000000

Symbol  DevAdr = B0		'
Symbol  EEAdr = B1

Symbol T = W1
Symbol L = B2
Symbol H = B3


' Used in I2C Routines
Symbol  OByte = B4
Symbol  IByte = B4
Symbol  Ack = B5
Symbol  N = B6
Symbol  MSBit = B7
Symbol X = B8


    Pause 3000
Top:

    DirsC = $00
    GoSub DS1624Config        ' configure DS1624 for 1SHOT operation

    For EEAdr = 0 TO 9      ' make ten measurements
        GoSub DS1624Init       ' initiate a conversion
        GoSub DS1624Meas       ' fetch the result

        SerTxD (#H, "  ", #L, 13, 10)

        Gosub DS1624EEWrite   ' save high byte to the DS1624 EEPROM
        Pause 1000
     Next

     For EEAdr = 0 TO 9      ' now fetch each from EEPROM and display
        GoSub DS1624EERead
        SerTxD(#EEAdr, "  ", #H, 13, 10)
     Next


Done:
     GoTo Done

DS1624Config:   ' configures DS1624 in 1SHOT temperature conversion mode
     Gosub I2CStart

     OByte = 2 * DevAdr + $90
     Gosub I2COutByte

     OByte = $AC          'Access Config
     GoSub I2COutByte


     OByte = $01          '1 SHOT mode
     Gosub I2COutByte


     Gosub I2CStop
     Pause 30            ' wait for EEPROM to program

     Return

DS1624Init:     ' causes DS1624 to initiate a conversion

     Gosub I2CStart
     OByte = 2 * DevAdr + $90
     Gosub I2COutByte


     OByte = $EE          ' Start Conversion
     Gosub I2COutByte

     Gosub I2CStop
     Pause 1000          ' wait 1000 ms for conversion to complete

     Return

DS1624Meas:     ' fetches temperature result.  Value returned in T_HI and T_LO

     Gosub I2CStart
     OByte = 2 * DevAdr + $90
     Gosub I2COutByte


     OByte = $AA          ' Fetch Temperature
     Gosub I2COutbyte


     Gosub I2CStart         ' read
     OByte = 2 * DevAdr + $91
     Gosub I2COutByte

     Ack = 1
     Gosub I2CInByte       ' fetch the two byte reading
     H = IByte    ' high byte

     Ack = 0
     Gosub I2CInByte       ' fetch the two byte reading
     L = IByte    ' low byte

     GoSub I2CStop

     Return

DS1624EERead:  ' fetches content location ADR in DS1624 EEPROM

     Gosub I2CStart
     OByte = 2 * DevAdr + $90
     Gosub I2COutByte

     OByte = $17          ' access EEPROM
     Gosub I2COutByte


     OByte = EEAdr          ' specify address to read
     Gosub I2COutByte

     Gosub I2CStart         ' read
     OByte = 2 * DevAdr + $91
     Gosub I2COutByte


     Ack = 0
     Gosub I2CInByte

     Gosub I2CStop
     H = IByte
     Return

DS1624EEWrite: ' writes content of DAT to specified address ADR

     Gosub I2CStart
     OByte = 2 * DevAdr + $90
     Gosub I2COutByte

     OByte = $17          ' access EEPROM
     Gosub I2COutByte


     OByte = EEAdr          ' specify address to read
     Gosub I2COutByte

     OByte = H          ' data to write
     Gosub I2COutByte

     'Pause 50
     Gosub I2CStop
     Pause 50            ' wait for EEPROM to program

     Return


I2CStart:
    GoSub SDAHigh
    GoSub SCLHigh
    GoSub SDALow				' bring SDA low when SCL is high
    GoSub SCLLow
    Return

I2CStop:
    GoSub SCLHigh
    GoSub SDAHigh				' bring SDA high when SCL is high
    Return

I2COutByte:

    For N = 1 to 8
       MSBit = OByte / 128
       If MSBit = 1 Then I2COutByte_1 	' most sign bit

       GoSub SDALow
       GoTo I2COutByte_2
I2COutByte_1:
       GoSub SDAHigh
I2COutByte_2:
       GoSub SCLHigh
       GoSub SCLLow
       OByte = OByte * 2	' shift byte such that next bit is in most sig bit position
    Next
    GoSub SDAHigh 				' null clock pulse to allow for slave to acknowledge
    GoSub SCLHigh
    GoSub SCLLow
    GoSub SDALow
    Return

I2CInByte:  ' receives a byte, most sig byte first.
          ' result returned in I_BYTE
     Gosub SDAHigh
     IByte = 0 ' not necessary
     For N = 0 TO 7
        Gosub SCLHigh
        IByte = IByte * 2 + Input6
        SerTxD (#IByte, " ")
        Gosub SCLLow
     Next
     SerTxD(10, 13) ' for debugging
     Branch Ack, (NoAck, YesAck)

NoAck:
     GoSub SDAHigh
     Goto I2CInByte1

YesAck:
     Gosub SDALow
I2CInByte1:
     Gosub SCLHigh
     Gosub SCLLow

     Gosub SDALow

     Return


SDAHigh:
    Peek $87, X
    X = X ^ $ff & SDADirIn
    DirsC = X
    'SerTxD (#X, " ")
    Return

SDALow:
    Peek $07, X
    X = X & SDAState0
    PinsC = X

    Peek $87, X
    X = X ^ $ff | SDADir0ut
    DirsC = X

    Return


SCLHigh:
    Peek $87, X
    X = X ^ $ff & SCLDirIn
    DirsC = X
    'SerTxD (#X, " ")
    Return


SCLLow:
    Peek $07, X
    X = X & SCLState0
    PinsC = X
    Peek $87, X

    X = X ^ $ff | SCLDirOut
    DirsC = X
    'SerTxD (#X, " ")
    Return