Interfacing with a Dallas DS1803 Dual Potentiometer
/* Program DS1803_1.C
**
** Illustrates how to control a Dallas DS1803 Addressable Dual
** Potentiometer.
**
** Flashlite V25 DS1803
**
** P2.1 ------------------- SCL ----- To Other
** P2.0 ------------------- SDA ----- I2C Devices
**
** Note that the slave 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 $55 and Pot 1 to $80. The settings of the
** two pots are then read from the 1803 and displayed on the terminal.
**
** copyright Peter H. Anderson and Onya Barnes, Baltimore, MD, Oct. '00
*/
#include <stdio.h>
#include <dos.h>
#define SEG 0xf000
#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12
#define NEW /* use "?:" construct in in_byte() and out_byte() */
typedef unsigned char byte;
void ds1803_write_pot(byte device, byte pot, byte setting);
void ds1803_read_pots(byte device, byte *p_setting_0, byte *p_setting_1);
/*common i2c routines*/
byte i2c_in_byte(void);
void i2c_out_byte(byte o_byte);
void i2c_nack(void);
void i2c_ack(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_high_sda(void);
void i2c_low_sda(void);
void i2c_high_scl(void);
void i2c_low_scl(void);
/* note global */
byte far *p2;
byte far *pm2;
byte far *pmc2;
byte dirs2, outs2;
void main(void)
{
byte pot_setting_0, pot_setting_1;
p2=MK_FP(SEG, P2_OFFSET);
pm2=MK_FP(SEG, PM2_OFFSET);
pmc2=MK_FP(SEG, PMC2_OFFSET);
dirs2=0xff;
*pmc2=0x00;
*pm2=dirs2;
ds1803_write_pot(0x00, 0, 0x55); /*dev 0, pot 0, setting 0x55*/
ds1803_write_pot(0x00, 1, 0x80);
ds1803_read_pots(0, &pot_setting_0, &pot_setting_1);
printf("%d %d\n", pot_setting_0, pot_setting_1);
}
void ds1803_write_pot(byte device, byte pot, byte setting)
/*writes specified setting to specified potentiometer on specified device*/
{
i2c_start();
i2c_out_byte(0x50 | (device << 1));
i2c_nack();
i2c_out_byte(0xa9 + pot); /*0xa9 for pot 0, 0xaa for pot 1*/
i2c_nack();
i2c_out_byte(setting);
i2c_nack();
i2c_stop();
delay(25000); /*wait for it to burn into EEPROM*/
}
void ds1803_read_pots(byte device, byte *p_setting_0, byte *p_setting_1)
/*reads data from both potentiometers*/
{
i2c_start();
i2c_out_byte(0x51 | (device << 1));
i2c_nack();
*p_setting_0 = i2c_in_byte();
i2c_ack();
*p_setting_1 = i2c_in_byte();
i2c_ack();
i2c_stop();
}
/* Common I2C Routines*/
byte i2c_in_byte(void)
{
byte i_byte=0, n;
i2c_high_sda();
for (n=0; n<8; n++)
{
i2c_high_scl();
#ifdef NEW
(*(p2) & 0x01) ? ((i_byte << 1) | 0x01) : (i_byte << 1);
#else
if (*p2) & 0x01)
{
i_byte = (i_byte << 1) | 0x01; /* msbit first */
}
else
{
i_byte = i_byte << 1;
}
#endif
i2c_low_scl();
}
return(i_byte);
}
void i2c_out_byte(byte o_byte)
{
byte n;
for(n=0; n<<8; n++)
{
#ifdef NEW /* use of the "? :" construct */
(o_byte&0x80) ? (i2c_high_sda()) : (i2c_low_sda());
#else
if (o_byte&0x80)
{
i2c_high_sda();
}
else
{
i2c_low_sda();
}
#endif
i2c_high_scl();
i2c_low_scl();
o_byte = o_byte << 1;
}
i2c_high_sda();
}
void i2c_nack(void)
{
i2c_high_sda(); /* data at one */
i2c_high_scl(); /* clock pulse */
i2c_low_scl();
}
void i2c_ack(void)
{
i2c_low_sda(); /* bring data low and clock */
i2c_high_scl();
i2c_low_scl();
i2c_high_sda();
}
void i2c_start(void)
{
i2c_low_scl();
i2c_high_sda();
i2c_high_scl(); /* bring SDA low while SCL is high */
i2c_low_sda();
i2c_low_scl();
}
void i2c_stop(void)
{
i2c_low_scl();
i2c_low_sda();
i2c_high_scl();
i2c_high_sda(); /* bring SDA high while SCL is high */
/* idle is SDA high and SCL high */
}
void i2c_high_sda(void)
{
dirs2 = dirs2 | 0x01;
*pm2 = dirs2;
#ifdef D /* used for debugging */
printf("SDA_HIGH %x\n", dirs2);
delay(500);
#endif
}
void i2c_low_sda(void)
{
outs2 = outs2 & (~0x01); /* zero the output pin */
*p2 = outs2;
dirs2 = dirs2 & (~0x01); /* and output */
*pm2 = dirs2;
#ifdef D
printf("SDA_LOW %x\n", dirs2);
delay(500);
#endif
}
void i2c_high_scl(void)
{
dirs2 = dirs2 | 0x02; /* bring SCL to high impedance */
*pm2 = dirs2;
#ifdef D
printf("SCL_HIGH %x\n", dirs2);
delay(500);
#endif
}
void i2c_low_scl(void)
{
outs2 = outs2 & (~0x02);
*p2 = outs2; /* zero the output pin */
dirs2 = dirs2 & (~0x02); /* and output */
*pm2 = dirs2;
#ifdef D
printf("SCL_LOW %x\n", dirs2);
delay(500);
#endif
}