' DS1803.Bas (PICAXE-18X)
'
' Illustrates how to control a DS1803 Addressable Dual Potentiometer.
'
' Configures Pot0 for 128 (half scale) and Pot1 for 64 (quarter scale).
' Reads and displays the values of the two pots.
'
' PICAXE-18X		            DS1803
'
' Output0 (term 6) ------------- SCL (term 9) ---------- To other I2C devices
' Output1 (term 7) -- 4.7K ----- SDA (term 10) ----------
'                           |
' Input1 (term 18) ---------

' The manufacturer's device code foe the DS1803 is 0101.
'
' Note that the secondary address is determined by A2 (term 4), A1 (term 5)
' and A0 (term 6) on the 1803.  The above SCL and SDA leads may be multipled
' to eight devices, each strapped for a unique A2 A1 A0 setting.
'
' Pot 0 is set to a value of 128 and Pot 1 to 64.  The settings of the
' two pots are then read from the 1803 and displayed on the screen.
'
' copyright Peter H. Anderson, Elmore, VT, Aug, '04

' Define IO Terminals
Symbol SCL = 0
Symbol SDAIn = Pin1
Symbol SDAOut = 1

Symbol  DevAdr = B0

Symbol PotNum = B1
Symbol PotSetting0 = B2
Symbol PotSetting1 = B3


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


   Pause 3000
Top:
   DevAdr = 0
   
   PotNum = 0
   PotSetting0 = 128
   GoSub DS1803WritePot

   PotNum = 1
   PotSetting1 = 64
   Gosub DS1803WritePot
   
   Gosub DS1803ReadPots
   SerTxD (#PotSetting0, "  ", #PotSetting1, 13, 10)
   
Done:
   Goto Done


DS1803WritePot:
    Branch PotNum, (WritePot0, WritePot1)

WritePot0:
    Gosub I2CStart

    OByte = 2 * DevAdr + $50
    Gosub I2COutByte

    OByte = $A9
    GoSub I2COutByte

    OByte = PotSetting0
    GoSub I2COutByte

    Gosub I2CStop

    Goto DS1803WritePotDone

WritePot1:
    Gosub I2CStart

    OByte = 2 * DevAdr + $50
    Gosub I2COutByte

    OByte = $AA
    GoSub I2COutByte

    OByte = PotSetting1
    GoSub I2COutByte

    Gosub I2CStop

    Goto DS1803WritePotDone

DS1803WritePotDone:

    Return

DS1803ReadPots:

    Gosub I2CStart

    OByte = 2 * DevAdr + $51
    Gosub I2COutByte

    Ack = 1		' master is to ACK after receipt of byte
    Gosub I2CInByte
    PotSetting0 = IByte

    Ack = 0		' no ACK as this is the last byte prior to the stop
    Gosub I2CInByte
    PotSetting1 = IByte

    Return

I2CStart:
    High SDAOut
    High SCL
    Low SDAOut			' bring SDA low while SCL is high
    Low SCL
    Return

I2CStop:
    High SCL
    High SDAOut         ' bring SDA high while SCL is high
    Return


I2COutByte:

    For N = 1 to 8      ' for eight bits
       MSBit = OByte / 128  ' beginning with the MSB
       If MSBit = 1 Then I2COutByte_1 	' most sig bit

       Low SDAOut
       GoTo I2COutByte_2
I2COutByte_1:
       High SDAOut
I2COutByte_2:
       High SCL
       Low SCL
       OByte = OByte * 2	' shift byte such that next bit is in most sig bit position
    Next
    High SDAOut 			' null clock pulse to allow for slave to acknowledge
    High SCL
    Low SCL
    Low SDAOut
    Return

I2CInByte:  ' receives a byte, most sig byte first.
          ' result returned in I_BYTE
    High SDAOut
    For N=1 to 8             ' for eight bits
       High SCL
       IByte = IByte * 2 + SDAIn
       Low SCL
    Next
    Branch Ack, (NoAck, YesAck)

NoAck:
     High SDAOut             ' high Z on 9th clock pulse
     Goto I2CInByte1

YesAck:
     Low SDAOut              ' logic zero on 9th clock pulse
I2CInByte1:
     High SCL
     Low SCL

     Low SDAOut

     Return