From 18e0d79f4fe53fb3b24f6ae24b032db657332ed2 Mon Sep 17 00:00:00 2001
From: Tom Aarts
Date: Fri, 4 Sep 2026 19:54:13 -0500
Subject: [PATCH 1/2] mcp4728 example device
---
README.md | 1 +
assets/runMcp4728.sh | 2 +
pom.xml | 2 +-
.../com/pi4j/devices/mcp4728/MCP4728App.java | 305 ++++++++++++++++++
.../devices/mcp4728/MCP4728_Declares.java | 69 ++++
.../java/com/pi4j/devices/mcp4728/README.md | 110 +++++++
6 files changed, 488 insertions(+), 1 deletion(-)
create mode 100644 assets/runMcp4728.sh
create mode 100644 src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
create mode 100644 src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java
create mode 100644 src/main/java/com/pi4j/devices/mcp4728/README.md
diff --git a/README.md b/README.md
index e0d61aa..323d68b 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@ The following table the currently supported devices within this project:
| A/D | SPI | | [MCP3008 A/D 10bit converter](src/main/java/com/pi4j/devices/mcp3008/README.md)
| A/D | SPI | | [MCP3208 A/D 12bit converter](src/main/java/com/pi4j/devices/mcp3208/README.md)
| D/A | I2C | | [MCP4725 12 bit DAC](src/main/java/com/pi4j/devices/mcp4725/README.md)
+| D/A | I2C | | [MCP4728 12 bit DAC 4-ch](src/main/java/com/pi4j/devices/mcp4728/README.md)
| D/A | SPI | | [MCP4921 12 bit DAC](src/main/java/com/pi4j/devices/mcp4921/README.md)
| D/A | SPI | | [MCP4922 12 bit DAC](src/main/java/com/pi4j/devices/mcp4922/README.md)
| HAT | | | [Raspberry SenseHat](src/main/java/com/pi4j/examples/hat/raspberry/sensehat/)
diff --git a/assets/runMcp4728.sh b/assets/runMcp4728.sh
new file mode 100644
index 0000000..20e88ee
--- /dev/null
+++ b/assets/runMcp4728.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+ java -classpath ./*:../classes com.pi4j.devices.mcp4728.MCP4728App $@
diff --git a/pom.xml b/pom.xml
index 9319175..b4292f8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
2.0.17
4.0.1
-
+
1.6.0
diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
new file mode 100644
index 0000000..428d7d2
--- /dev/null
+++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
@@ -0,0 +1,305 @@
+
+
+package com.pi4j.devices.mcp4728;
+
+import com.pi4j.Pi4J;
+import com.pi4j.context.Context;
+import com.pi4j.drivers.io.da.mcp472x.Mcp4728Driver;
+import com.pi4j.io.gpio.digital.DigitalInput;
+import com.pi4j.io.gpio.digital.DigitalInputConfigBuilder;
+import com.pi4j.io.gpio.digital.PullResistance;
+import com.pi4j.io.i2c.I2C;
+import com.pi4j.io.i2c.I2CImplementation;
+import com.pi4j.util.Console;
+
+/**
+ * Support MCP4728 DAC.
+ *
+ * Support the single channel functions of the chip. Example: you cannot set
+ * all four channels vref bit in a single call. Rather this would require
+ * four separate calls to the driver code.
+ *
+ *
+ * *The MCP4728 ships with device address 0x60. To set other address the DAC config registers
+ * * must be updated. The update process requires the LDAC pin be toggled at a specific point
+ * * in the I2C command as it is clocked into the chip. This GPIO control within the I2C
+ * * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with
+ * * the address programmed, or use of an MCU.
+ * *
+ * * @see MCP4728
+ * *
+ *
+ */
+public class MCP4728App {
+
+ static void main(String[] args) {
+ System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "NONE");
+
+ Context pi4j = Pi4J.newAutoContext();
+
+ final Console console = new Console();
+ console.print("==============================================================");
+ console.print("startup MCP4728App ");
+ console.print("==============================================================");
+
+
+
+ int dataPinNum = -1;
+ int busNum = 1;
+ int address = MCP4728_Declares._MCP4728_DEFAULT_ADDRESS;
+ int channel = 0;
+ boolean doReset = false;
+ int registerData = 0;
+ boolean setOutputEEPROM = false;
+ boolean setOutputFast = false;
+ double vref = 0;
+ float eepromVolt = 0;
+ float fastVolt = 0;
+ int onlyOne = 0; // numerous parms a mutually exclusive
+ int gainBit = 0;
+ int vrefBit = 1;
+ boolean setVrefBit = false;
+ boolean setGainBit = false;
+ boolean updateEEPROM = false;
+
+ String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address -d RDY GPIO number \n " +
+ " -r reset chip -ue update EEPROM -rde update DAC and EEPROM \n" +
+ " -ev eeprom voltage -fv fast voltage \n" +
+ " -rdf DAC value update fast -vdd decimal reference voltage\n " +
+ " -ch channel A B C D -sv vref 0 or 1 -sg gain 0 or 1" +
+ "-rde -ev -fv -rdf -sv -sg mutually exclusive " ;
+
+ for (int i = 0; i < args.length; i++) {
+ String o = args[i];
+ if (o.contentEquals("-b")) { // bus
+ String a = args[i + 1];
+ busNum = Integer.parseInt(a.substring(2), 16);
+ i++;
+ } else if (o.contentEquals("-a")) { // device address
+ String a = args[i + 1];
+ i++;
+ address = Integer.parseInt(a.substring(2), 16);
+ } else if (o.contentEquals("-d")) {
+ String a = args[i + 1];
+ dataPinNum = Integer.parseInt(a);
+ i++;
+ } else if (o.contentEquals("-sv")) {
+ String a = args[i + 1];
+ vrefBit = Integer.parseInt(a);
+ setVrefBit = true;
+ if ( (vrefBit <0) || (vrefBit > 1) ){
+ console.println("-vref must be in range 0..1");
+ System.exit(54);
+ }
+ i++;
+ onlyOne ++;
+ } else if (o.contentEquals("-sg")) {
+ String a = args[i + 1];
+ gainBit = Integer.parseInt(a);
+ setGainBit = true;
+ if ( (gainBit <0) || (gainBit > 1) ){
+ console.println("-vref must be in range 0..1");
+ System.exit(55);
+ }
+ i++;
+ onlyOne ++;
+ } else if (o.contentEquals("-ch")) {
+ String a = args[i + 1];
+ i++;
+ if (a.equalsIgnoreCase("A")) {
+ channel = 0;
+ } else if (a.equalsIgnoreCase("B")) {
+ channel = 1;
+ } else if (a.equalsIgnoreCase("C")) {
+ channel = 2;
+ } else if (a.equalsIgnoreCase("D")) {
+ channel = 3;
+ } else {
+ console.println(" -ch invalid ");
+ System.exit(53);
+ }
+ } else if (o.contentEquals("-vdd")) { // reference voltage
+ String a = args[i + 1];
+ i++;
+ vref = Float.parseFloat(a);
+ } else if (o.contentEquals("-r")) {
+ doReset = true;
+ } else if (o.contentEquals("-ue")) {
+ updateEEPROM = true;
+ } else if (o.contentEquals("-rde")) {
+ String a = args[i + 1];
+ i++;
+ registerData = Integer.parseInt(a);
+ setOutputEEPROM = true;
+ if (registerData < 0 || registerData > 4095) {
+ console.println("-rde must be in range 0..4095");
+ System.exit(36);
+ }
+ onlyOne ++;
+ } else if (o.contentEquals("-rdf")) {
+ String a = args[i + 1];
+ i++;
+ setOutputFast = true;
+ registerData = Integer.parseInt(a);
+ if (registerData < 0 || registerData > 4095) {
+ console.println("-rdf must be in range 0..4095");
+ System.exit(37);
+ }
+ onlyOne ++;
+ } else if (o.contentEquals("-h")) {
+ console.println(helpString);
+ System.exit(39);
+ } else if (o.contentEquals("-ev")) { // eeprom volts
+ String a = args[i + 1];
+ i++;
+ eepromVolt = Float.parseFloat(a);
+ onlyOne ++;
+ } else if (o.contentEquals("-fv")) { // fast volts
+ String a = args[i + 1];
+ i++;
+ fastVolt = Float.parseFloat(a);
+ onlyOne ++;
+ } else {
+ console.println(" !!! Invalid Parm " + args);
+ console.println(helpString);
+ System.exit(42);
+ }
+ }
+
+ if ( dataPinNum == -1 ){
+ console.println(" Parameter -d, gpio BCM must be set.");
+ console.println(helpString);
+ System.exit(54);
+ }
+ if (onlyOne > 1 ) {
+ console.println(" mutually exclusive parms used.");
+ console.println(helpString);
+ System.exit(43);
+ }
+
+ if ( (vref == 0) || (vref < 0) ){
+ console.println("-vdd is zero or less than zero");
+ System.exit(50);
+
+ }
+ if ( (eepromVolt > vref) || (eepromVolt < 0) ) {
+ console.println("-ev greater than -vdd, or less than zero");
+ System.exit(51);
+
+ }
+
+ if ( (fastVolt > vref) || (fastVolt < 0) ) {
+ console.println("-ef greater than -vdd, or less than zero");
+ System.exit(52);
+
+ }
+
+ Mcp4728Driver dacChip ;
+ I2C genCallDevice = null ;
+ DigitalInput readyPin = createInputGPIO(dataPinNum, pi4j);
+
+
+ I2C i2cDev = createI2cDevice("MCP4728", busNum, address, I2CImplementation.DIRECT, pi4j) ;
+ dacChip = new Mcp4728Driver( i2cDev, readyPin, vref);
+
+
+ if (doReset) {
+ genCallDevice = createI2cDevice("GenCallReset", busNum,0x00, I2CImplementation.SMBUS, pi4j);
+ dacChip.resetChip(genCallDevice);
+ }
+
+ console.println(dacChip.materializeDacDescription());
+
+ if (setGainBit) {
+ dacChip.setGain(channel,gainBit);
+ }
+
+ if (setVrefBit) {
+ dacChip.setVref(channel,vrefBit);
+ }
+
+ if (setOutputEEPROM) {
+ try {
+ dacChip.setDigitalValueDACEEPROM(channel, registerData);
+ } catch (Exception e) {
+ console.println("Error occurred setting DAC output via register value failed. \n Exception " + e.getMessage());
+ }
+ }
+ if (setOutputFast) {
+ dacChip.setDigitalValueDAC(channel, registerData);
+ }
+
+ if (eepromVolt > 0) {
+ try {
+ dacChip.setVoltage(channel, eepromVolt);
+ } catch (Exception e) {
+ console.println("Error occurred setting DAC output via target voltage failed. \n Exception " + e.getMessage());
+ }
+ }
+
+
+ if (fastVolt > 0) {
+ dacChip.materializeDacRegs() ;
+ dacChip.setVoltage(channel, fastVolt);
+ dacChip.materializeDacRegs() ;
+ }
+
+ if (updateEEPROM) {
+ dacChip.syncDACToEEPROM();
+ }
+
+ console.println(dacChip.materializeDacDescription());
+
+
+ if (genCallDevice != null) {
+ genCallDevice.close();
+ }
+ if (i2cDev != null) {
+ i2cDev.close();
+ }
+
+
+ }
+
+
+ /**
+ *
+ * @param pinNumber GPIO number
+ * @param pi4j Context
+ * @return
+ */
+ static DigitalInput createInputGPIO(int pinNumber, Context pi4j){
+ DigitalInputConfigBuilder inputConfig1 = DigitalInput.newConfigBuilder(pi4j)
+ .id("Data_In_" + pinNumber)
+ .name("Data_In_" + pinNumber)
+ .bcm(pinNumber)
+ .pull(PullResistance.PULL_UP);
+ return pi4j.create(inputConfig1);
+ }
+
+ /**
+ *
+ * @param chipType String Part numer
+ * @param bus INT
+ * @param address INT
+ * @param pi4j Context
+ * @return
+ */
+ static I2C createI2cDevice( String chipType, int bus, int address, I2CImplementation impType, Context pi4j) {
+ String id = String.format("0X%02x: ", bus);
+ String name = String.format("0X%02x: ", address);
+ var i2cDeviceConfig = I2C.newConfigBuilder(pi4j)
+ .bus(bus)
+ .device(address)
+ .id(chipType + id + " " + name)
+ .name(name)
+ .i2cImplementation(impType)
+ .build();
+
+ return pi4j.create(i2cDeviceConfig);
+
+
+ }
+
+}
+
diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java
new file mode 100644
index 0000000..3a89744
--- /dev/null
+++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java
@@ -0,0 +1,69 @@
+
+
+package com.pi4j.devices.mcp4728;
+
+
+
+public class MCP4728_Declares {
+ public static final int _MCP4728_DEFAULT_ADDRESS = 0x60;
+
+ public static final int _MCP4728_SET_EEPROM_SIZE = 0x06;
+ public static final int _MCP4728_SET_FAST_SIZE = 0x04;
+ public static final int _MCP4728_CHIP_READ_SIZE = 0x05;
+
+ // Table 5.1
+ public static final byte _MCP4728_WRITE_CMD_FAST = 0b00000000;
+ public static final byte _MCP4728_WRITE_CMD_MULTI_DAC_EEPROM = 0b01000000;
+ public static final byte _MCP4728_WRITE_CMD_SNGL_DAC_EEPROM = 0b01011000;
+
+ public static final byte _MCP4728_WRITE_CMD_I2C_ADDR = 0b01100000;
+
+
+ public static final byte _MCP4728_WRITE_CMD_SEQ_DAC_EEPROM = 0b01010000;
+
+ public static final byte _MCP4728_WRITE_CMD_VREF_SLCT_DAC = (byte) 0b10000000;
+ public static final byte _MCP4728_WRITE_CMD_GAIN_SLCT_DAC = (byte) 0b11000000;
+ public static final byte _MCP4728_WRITE_CMD_PD_BITS_DAC = (byte) 0b10100000;
+
+
+
+
+
+
+
+ public static final byte _MCP4728_PD_MODE_NORMAL = 0b00000000;
+ public static final byte _MCP4728_PD_MODE_INOPT = 0b00000110;
+
+ public static final byte _MCP4728_DAC_PD0_MODE_MASK = 0b00000010;
+ public static final byte _MCP4728_DAC_PD1_MODE_MASK = 0b00000100;
+
+ public static final int _MCP4728_EEPROM_PD1_MODE_MASK = 0b10000000;
+ public static final byte _MCP4728_EEPROM_PD0_MODE_MASK = 0b01000000;
+
+ // Indicate EEPROM write/update status
+ public static final byte _MCP4728_READ_CMD_RDY_BSY_MSK = (byte) 0b10000000;
+ public static final byte _MCP4728_READ_CMD_IS_COMPLT = (byte) 0b10000000;
+ public static final byte _MCP4728_READ_CMD_IS_NOT_COMPLT = (byte) 0b00000000;
+
+ // POR device load EEPROM
+ public static final byte _MCP4728_GEN_CALL_RESET_CMD = (byte) 0b00000110;
+
+ // POR device PD1 and PD0 set to 0 for normal operation
+ public static final byte _MCP4728_GEN_CALL_WAKEUP_CMD = (byte) 0b00001001;
+
+
+ // Write
+ // C2=0 C1=1 C0=0 DAC only
+ // C2=0 C1=1 C0=1 DAC and EEPROM
+ // byte1 byte2 byte3 byte4
+ // address r/w C2 C1 C0 x x PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X X X X
+
+ // Read DAC
+ // byte1 byte2 byte3 byte4
+ // address r/w RDY/BSY C1 C0 x x PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X X X X
+
+ // EEPROM
+ // byte5 byte6
+ // X PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
+
+}
diff --git a/src/main/java/com/pi4j/devices/mcp4728/README.md b/src/main/java/com/pi4j/devices/mcp4728/README.md
new file mode 100644
index 0000000..32b04ec
--- /dev/null
+++ b/src/main/java/com/pi4j/devices/mcp4728/README.md
@@ -0,0 +1,110 @@
+### This repository contains device specific support for various devices.
+
+### This is an example implementation and will need to be adjusted to fit your needs.
+
+Project by Tom Aarts
+==========================================================================
+
+ Adafruit MCP4728
+
+Pi 3.3V Vin
+Pi Grnd GND
+Pi Pin5 SCL
+Pi Pin3 SDA
+Pi Grnd LDAC
+P1 Gpio12 RDY/BSY
+ Ch B MCP3008 ch6
+ Ch D MCP3008 ch1
+
+
+
+1. ./mvnw clean package
+2. cd target/distribution
+3. sudo ./runMcp4728.sh parms........
+
+https://datasheetspdf.com/pdf-file/634126/MicrochipTechnology/MCP4728/1
+
+-rde anf -rdf both have max input value 0x0FFF
+
+-ef and -ev cannot exceed -vdd
+
+
+
+ Read output votage on channel 1 of MCP3008
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch D
+
+
+ All remainig examples read output votage on channel 6 of MCP3008
+
+Updates using raw binary value
+To Update DAC and EEPROM, set to 50 % of reference voltage Vin of 3.3 volts
+
+vrefBit 1 by default vout = 1.0v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12
+
+set vrefBit 0, uses vdd
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12
+
+vrefBit 0 vout = 1.6 v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12
+
+To Update DAC Fast, set to 50 % of reference voltage
+vrefBit 0, vout 1.6v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12
+
+set vrefBit 1, uses 2.048
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -d 12
+
+set vrefBit 1, set gain to 2x
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12
+
+To Update DAC Fast, set to 50 % of reference voltage
+vrefBit 0, gain 2x vout 3.3v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12
+
+
+To Update DAC Fast, set to 100 % of reference voltage
+vrefBit 0, vout 3.3v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 4095 -r -vdd 3.3 -ch B -d 12
+
+Updates using voltage value
+
+To Update DAC Fast, set to 1.8v of reference voltage
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -fv 1.8 -vdd 3.3 -ch B -d 12
+
+To Update DAC and EEPROM, set to 3.3v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.3 -vdd 3.3 -ch B -d 12
+
+To Update DAC Fast, reset chip, set to 3.1
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12
+
+
+
+
+
+UNIT TEST
+Validate dumps registers show bits updated correctly
+
+To Update vref bit channel 1
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12
+
+To Update gain bit channel 1
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12
+
+
+
+
+vref 0 = vdd
+ 1 = 2.048
+
+gain 0 = 1
+ 1 = 2x
+
+
+
+Test program. Loop indefinitely executing the shell command
+
+./runLoop.sh program.sh args ......
+
+Example usage:
+./runLoop.sh ./runMcp3008.sh -vref 3.3 -p 0x0?
\ No newline at end of file
From 0de05a3b5d689f283d95acb4ffd4d5afb04e7fd5 Mon Sep 17 00:00:00 2001
From: Tom Aarts
Date: Fri, 4 Sep 2026 19:54:13 -0500
Subject: [PATCH 2/2] mcp4728 example device
# Conflicts:
# src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
# src/main/java/com/pi4j/devices/mcp4728/README.md
---
.../com/pi4j/devices/mcp4728/MCP4728App.java | 173 +++++++-----------
.../java/com/pi4j/devices/mcp4728/README.md | 84 ++++++---
2 files changed, 124 insertions(+), 133 deletions(-)
diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
index 428d7d2..34bfdc3 100644
--- a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
+++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java
@@ -5,35 +5,45 @@
import com.pi4j.Pi4J;
import com.pi4j.context.Context;
import com.pi4j.drivers.io.da.mcp472x.Mcp4728Driver;
-import com.pi4j.io.gpio.digital.DigitalInput;
-import com.pi4j.io.gpio.digital.DigitalInputConfigBuilder;
-import com.pi4j.io.gpio.digital.PullResistance;
import com.pi4j.io.i2c.I2C;
import com.pi4j.io.i2c.I2CImplementation;
import com.pi4j.util.Console;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Support MCP4728 DAC.
*
- * Support the single channel functions of the chip. Example: you cannot set
+ * Support the single channel at a time functions of the chip. Example: you cannot set
* all four channels vref bit in a single call. Rather this would require
* four separate calls to the driver code.
*
*
- * *The MCP4728 ships with device address 0x60. To set other address the DAC config registers
- * * must be updated. The update process requires the LDAC pin be toggled at a specific point
- * * in the I2C command as it is clocked into the chip. This GPIO control within the I2C
- * * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with
- * * the address programmed, or use of an MCU.
- * *
- * * @see MCP4728
- * *
+ * The MCP4728 ships with device address 0x60. To set other address the DAC config registers
+ * must be updated. The update process requires the LDAC pin be toggled at a specific point
+ * in the I2C command as it is clocked into the chip. This GPIO control within the I2C
+ * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with
+ * the address programmed, or use of an MCU.
+ *
+ * @see MCP4728
+ *
+ *
+ * The MCP4728 chip contains an EEPROM. When Powered-on or RESET, the EEPROM contents are used to update
+ * the DAC volatile registers, restoring the configured output voltages. The program arguments that result
+ * in the EEPROM being updated that code examples include the statement dacChip.setEepromEnabled(true);.
+ * After this method all subsequent methods will ensure the EEPROM is updated. To stop this behavior the
+ * examples call dacChip.setEepromEnabled(false);
+ *
+ * The example uses the letters A B C D to specify the channel. This conforms to the chips Datasheet documentation.
+ * Within the driver method signatures and code the channel is specified with an int.
*
*/
public class MCP4728App {
static void main(String[] args) {
- System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "NONE");
+ System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO");
+ Logger logger = LoggerFactory.getLogger(MCP4728App.class);
+ logger.trace(">>> Enter: init");
Context pi4j = Pi4J.newAutoContext();
@@ -44,31 +54,30 @@ static void main(String[] args) {
- int dataPinNum = -1;
int busNum = 1;
int address = MCP4728_Declares._MCP4728_DEFAULT_ADDRESS;
int channel = 0;
boolean doReset = false;
int registerData = 0;
- boolean setOutputEEPROM = false;
- boolean setOutputFast = false;
- double vref = 0;
- float eepromVolt = 0;
- float fastVolt = 0;
+ double vref = 0;
+ float volts = 0;
int onlyOne = 0; // numerous parms a mutually exclusive
int gainBit = 0;
int vrefBit = 1;
boolean setVrefBit = false;
boolean setGainBit = false;
- boolean updateEEPROM = false;
+ boolean setOutputDigital = false;
+ boolean setOutputVotage = false;
+ boolean persistValues = false;
+
- String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address -d RDY GPIO number \n " +
- " -r reset chip -ue update EEPROM -rde update DAC and EEPROM \n" +
- " -ev eeprom voltage -fv fast voltage \n" +
- " -rdf DAC value update fast -vdd decimal reference voltage\n " +
- " -ch channel A B C D -sv vref 0 or 1 -sg gain 0 or 1" +
- "-rde -ev -fv -rdf -sv -sg mutually exclusive " ;
+ String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address \n " +
+ " -r reset chip -ch channel A B C D -d digital value (0 ... 4095) \n" +
+ " -v voltage (0 ... vdd) -pu persist values true/false -vdd decimal reference voltage \n" +
+ " -sv vrefBit 0 or 1 -sg gainBit 0 or 1 \n" +
+ "-d -v -sv -sg mutually exclusive \n" ;
+ ;
for (int i = 0; i < args.length; i++) {
String o = args[i];
if (o.contentEquals("-b")) { // bus
@@ -79,17 +88,13 @@ static void main(String[] args) {
String a = args[i + 1];
i++;
address = Integer.parseInt(a.substring(2), 16);
- } else if (o.contentEquals("-d")) {
- String a = args[i + 1];
- dataPinNum = Integer.parseInt(a);
- i++;
} else if (o.contentEquals("-sv")) {
String a = args[i + 1];
vrefBit = Integer.parseInt(a);
setVrefBit = true;
- if ( (vrefBit <0) || (vrefBit > 1) ){
- console.println("-vref must be in range 0..1");
- System.exit(54);
+ if ( (gainBit <0) || (gainBit > 1) ){
+ console.println("vrefBit must be in range 0..1");
+ System.exit(55);
}
i++;
onlyOne ++;
@@ -98,7 +103,7 @@ static void main(String[] args) {
gainBit = Integer.parseInt(a);
setGainBit = true;
if ( (gainBit <0) || (gainBit > 1) ){
- console.println("-vref must be in range 0..1");
+ console.println("gainBit must be in range 0..1");
System.exit(55);
}
i++;
@@ -124,53 +129,36 @@ static void main(String[] args) {
vref = Float.parseFloat(a);
} else if (o.contentEquals("-r")) {
doReset = true;
- } else if (o.contentEquals("-ue")) {
- updateEEPROM = true;
- } else if (o.contentEquals("-rde")) {
+ }else if (o.contentEquals("-pv")) {
String a = args[i + 1];
+ persistValues = Boolean.parseBoolean(a);
i++;
- registerData = Integer.parseInt(a);
- setOutputEEPROM = true;
- if (registerData < 0 || registerData > 4095) {
- console.println("-rde must be in range 0..4095");
- System.exit(36);
- }
- onlyOne ++;
- } else if (o.contentEquals("-rdf")) {
+ } else if (o.contentEquals("-d")) {
String a = args[i + 1];
i++;
- setOutputFast = true;
registerData = Integer.parseInt(a);
+ setOutputDigital = true;
if (registerData < 0 || registerData > 4095) {
- console.println("-rdf must be in range 0..4095");
- System.exit(37);
+ console.println("-rde must be in range 0..4095");
+ System.exit(36);
}
onlyOne ++;
- } else if (o.contentEquals("-h")) {
+ } else if (o.contentEquals("-h")) {
console.println(helpString);
System.exit(39);
- } else if (o.contentEquals("-ev")) { // eeprom volts
+ } else if (o.contentEquals("-v")) { // eeprom volts
String a = args[i + 1];
i++;
- eepromVolt = Float.parseFloat(a);
- onlyOne ++;
- } else if (o.contentEquals("-fv")) { // fast volts
- String a = args[i + 1];
- i++;
- fastVolt = Float.parseFloat(a);
+ setOutputVotage = true;
+ volts = Float.parseFloat(a);
onlyOne ++;
} else {
- console.println(" !!! Invalid Parm " + args);
+ console.println(" !!! Invalid Parm " + o);
console.println(helpString);
System.exit(42);
}
}
- if ( dataPinNum == -1 ){
- console.println(" Parameter -d, gpio BCM must be set.");
- console.println(helpString);
- System.exit(54);
- }
if (onlyOne > 1 ) {
console.println(" mutually exclusive parms used.");
console.println(helpString);
@@ -182,13 +170,13 @@ static void main(String[] args) {
System.exit(50);
}
- if ( (eepromVolt > vref) || (eepromVolt < 0) ) {
- console.println("-ev greater than -vdd, or less than zero");
+ if ( (volts > vref) || (volts < 0) ) {
+ console.println("-v greater than -vdd, or less than zero");
System.exit(51);
}
- if ( (fastVolt > vref) || (fastVolt < 0) ) {
+ if ( (volts > vref) || (volts < 0) ) {
console.println("-ef greater than -vdd, or less than zero");
System.exit(52);
@@ -196,11 +184,10 @@ static void main(String[] args) {
Mcp4728Driver dacChip ;
I2C genCallDevice = null ;
- DigitalInput readyPin = createInputGPIO(dataPinNum, pi4j);
-
+
I2C i2cDev = createI2cDevice("MCP4728", busNum, address, I2CImplementation.DIRECT, pi4j) ;
- dacChip = new Mcp4728Driver( i2cDev, readyPin, vref);
+ dacChip = new Mcp4728Driver( i2cDev, vref);
if (doReset) {
@@ -208,7 +195,9 @@ static void main(String[] args) {
dacChip.resetChip(genCallDevice);
}
- console.println(dacChip.materializeDacDescription());
+ logger.info("\nBefore state : \n" + dacChip);
+
+ dacChip.setEepromEnabled(persistValues);
if (setGainBit) {
dacChip.setGain(channel,gainBit);
@@ -218,37 +207,17 @@ static void main(String[] args) {
dacChip.setVref(channel,vrefBit);
}
- if (setOutputEEPROM) {
- try {
- dacChip.setDigitalValueDACEEPROM(channel, registerData);
- } catch (Exception e) {
- console.println("Error occurred setting DAC output via register value failed. \n Exception " + e.getMessage());
- }
- }
- if (setOutputFast) {
- dacChip.setDigitalValueDAC(channel, registerData);
+ if (setOutputDigital) {
+ dacChip.setDigitalValue(channel, registerData);
}
- if (eepromVolt > 0) {
- try {
- dacChip.setVoltage(channel, eepromVolt);
- } catch (Exception e) {
- console.println("Error occurred setting DAC output via target voltage failed. \n Exception " + e.getMessage());
- }
+ if (setOutputVotage) {
+ dacChip.setVoltage(channel, volts);
}
- if (fastVolt > 0) {
- dacChip.materializeDacRegs() ;
- dacChip.setVoltage(channel, fastVolt);
- dacChip.materializeDacRegs() ;
- }
-
- if (updateEEPROM) {
- dacChip.syncDACToEEPROM();
- }
- console.println(dacChip.materializeDacDescription());
+ logger.info("\nCompletion state : \n" + dacChip);
if (genCallDevice != null) {
@@ -262,20 +231,6 @@ static void main(String[] args) {
}
- /**
- *
- * @param pinNumber GPIO number
- * @param pi4j Context
- * @return
- */
- static DigitalInput createInputGPIO(int pinNumber, Context pi4j){
- DigitalInputConfigBuilder inputConfig1 = DigitalInput.newConfigBuilder(pi4j)
- .id("Data_In_" + pinNumber)
- .name("Data_In_" + pinNumber)
- .bcm(pinNumber)
- .pull(PullResistance.PULL_UP);
- return pi4j.create(inputConfig1);
- }
/**
*
@@ -283,7 +238,7 @@ static DigitalInput createInputGPIO(int pinNumber, Context pi4j){
* @param bus INT
* @param address INT
* @param pi4j Context
- * @return
+ * @return I2C device
*/
static I2C createI2cDevice( String chipType, int bus, int address, I2CImplementation impType, Context pi4j) {
String id = String.format("0X%02x: ", bus);
diff --git a/src/main/java/com/pi4j/devices/mcp4728/README.md b/src/main/java/com/pi4j/devices/mcp4728/README.md
index 32b04ec..7222386 100644
--- a/src/main/java/com/pi4j/devices/mcp4728/README.md
+++ b/src/main/java/com/pi4j/devices/mcp4728/README.md
@@ -12,7 +12,6 @@ Pi Grnd GND
Pi Pin5 SCL
Pi Pin3 SDA
Pi Grnd LDAC
-P1 Gpio12 RDY/BSY
Ch B MCP3008 ch6
Ch D MCP3008 ch1
@@ -22,6 +21,27 @@ P1 Gpio12 RDY/BSY
2. cd target/distribution
3. sudo ./runMcp4728.sh parms........
+-b 0x? hex value bus
+-a 0x?? hex value address
+-vdd float reference voltage
+-pv true/false. Persist values, default false.
+-r reset chip
+All following parms effect channel -ch
+-ch channel A B C D
+-d digital input 0 - 4095
+-v voltage 0 - vdd
+-sv vref 0 or 1
+-sg gain 0 or 1" +
+
+Note -v -d -sv -sg mutually exclusive
+
+String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address \n " +
+" -r reset chip -ch channel A B C D -d digital value (0 ... 4095) \n" +
+" -v voltage (0 ... vdd) -pv persist values true/false -vdd decimal reference voltage \n" +
+" -sv vrefBit 0 or 1 -sg gainBit 0 or 1 \n" +
+"-d -v -sv -sg mutually exclusive \n" ;
+
+
https://datasheetspdf.com/pdf-file/634126/MicrochipTechnology/MCP4728/1
-rde anf -rdf both have max input value 0x0FFF
@@ -36,47 +56,61 @@ sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch D
All remainig examples read output votage on channel 6 of MCP3008
+
+Assume starting with channel B vrefBit 1 use 2.048V, gainBit 0 1x
Updates using raw binary value
To Update DAC and EEPROM, set to 50 % of reference voltage Vin of 3.3 volts
vrefBit 1 by default vout = 1.0v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B
+
+vrefBit 1 by default vout = 1.0v persist values
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B -pv true
+
set vrefBit 0, uses vdd
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -pv true
-vrefBit 0 vout = 1.6 v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12
+vrefBit 0 persisted previous test vout = 1.6 v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B
-To Update DAC Fast, set to 50 % of reference voltage
-vrefBit 0, vout 1.6v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12
set vrefBit 1, uses 2.048
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -d 12
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -pv true
-set vrefBit 1, set gain to 2x
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12
+set gainBit 1, set gain to 2x
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -pv true
-To Update DAC Fast, set to 50 % of reference voltage
-vrefBit 0, gain 2x vout 3.3v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12
+To Update DAC Fast, set to 50 % of reference voltage with 2x gain
+50% 2.048 = 1.0v 2x 1.0 = 2.0v
+vrefBit 0, gain 2x vout 2.0v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B
+set vrefBit 0, uses vdd
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -pv true
+
To Update DAC Fast, set to 100 % of reference voltage
-vrefBit 0, vout 3.3v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 4095 -r -vdd 3.3 -ch B -d 12
+vrefBit 0, vout 3.2v 2x gain not used when vrefBit 0 (use vdd)
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 4095 -r -vdd 3.3 -ch B
Updates using voltage value
-To Update DAC Fast, set to 1.8v of reference voltage
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -fv 1.8 -vdd 3.3 -ch B -d 12
+To Update DAC Fast, set to 1.8v vout 1.8v
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 1.8 -vdd 3.3 -ch B
To Update DAC and EEPROM, set to 3.3v
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.3 -vdd 3.3 -ch B -d 12
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.3 -vdd 3.3 -ch B -pv true
+
+To set vrefBit 1
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -pv true
+
+To Update DAC and EEPROM, set to 3.3v ????
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.3 -vdd 3.3 -ch B -pv true
+
To Update DAC Fast, reset chip, set to 3.1
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.1 -r -vdd 3.3 -ch B
@@ -85,11 +119,13 @@ sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12
UNIT TEST
Validate dumps registers show bits updated correctly
-To Update vref bit channel 1
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12
+To Update vref bit channel 1 of MCP3008
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch D
+
+To Update gain bit channel 1 of MCP3008
+sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch D
+
-To Update gain bit channel 1
-sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12