Skip to content

Commit

Permalink
Add a glasgow voltage command-line verb.
Browse files Browse the repository at this point in the history
Also fix some glitches related to alerts.
  • Loading branch information
whitequark committed May 7, 2018
1 parent b122273 commit ad62d88
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 24 deletions.
24 changes: 12 additions & 12 deletions firmware/adc.c
Expand Up @@ -140,12 +140,10 @@ bool iobuf_set_alert(uint8_t mask,

if(!adc_reg_write(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;

return true;
}
}

return false;
return true;
}

bool iobuf_get_alert(uint8_t selector,
Expand All @@ -160,7 +158,7 @@ bool iobuf_get_alert(uint8_t selector,
if(!adc_reg_read(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;

if(!(control_byte & ADC081_BIT_ALERT_PIN_EN)) {
if(control_byte == 0) {
*low_millivolts = 0;
*high_millivolts = MAX_VOLTAGE;
return true;
Expand Down Expand Up @@ -193,22 +191,24 @@ bool iobuf_poll_alert(__xdata uint8_t *mask, bool clear) {
return false;

if(status_byte) {
__pdata uint8_t control_byte = 0;
*mask |= buffer->selector;

if(!adc_reg_read(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;

if(clear) {
// Actually clear alert
// Clear actual alert and re-arm the alert pin
if(!adc_reg_write(buffer->address, ADC081_REG_ALERT_STATUS, &status_byte, 1))
return false;
control_byte |= ADC081_BIT_ALERT_PIN_EN;
} else {
// Only clear alert pin status
__pdata uint8_t control_byte = 0;
if(!adc_reg_read(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;

// Only disarm the alert pin (so that alerts from other ADCs can be detected)
control_byte &= ~ADC081_BIT_ALERT_PIN_EN;
if(!adc_reg_write(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;
}

if(!adc_reg_write(buffer->address, ADC081_REG_CONFIGURATION, &control_byte, 1))
return false;
}
}

Expand Down
65 changes: 54 additions & 11 deletions software/glasgow/cli.py
@@ -1,5 +1,6 @@
import os
import argparse
import time

from fx2 import FX2DeviceError

Expand All @@ -13,6 +14,21 @@ def get_argparser():
subparsers = parser.add_subparsers(dest="action", metavar="COMMAND")
subparsers.required = True

p_voltage = subparsers.add_parser(
"voltage", help="query or set I/O port voltage")
p_voltage.add_argument(
"ports", metavar="PORTS", type=str, nargs='?', default="AB",
help="I/O port set (one or more of: A B, default: all)")
p_voltage.add_argument(
"voltage", metavar="VOLTS", type=float, nargs='?', default=None,
help="I/O port voltage (range: 1.8-5.0)")
p_voltage.add_argument(
"--tolerance", metavar="PCT", type=float, default=10.0,
help="raise alert if measured voltage deviates by more than ±PCT%%")
p_voltage.add_argument(
"--no-alert", dest="set_alert", default=True, action="store_false",
help="do not raise an alert if Vsense is out of range of Vio")

p_download = subparsers.add_parser(
"download", help="volatile download bitstream to FPGA")
p_download.add_argument(
Expand Down Expand Up @@ -40,18 +56,45 @@ def main():
try:
firmware_file = os.path.join(os.path.dirname(__file__), "glasgow.ihex")
device = GlasgowDevice(firmware_file)
except (FX2DeviceError, GlasgowDeviceError) as e:
raise SystemExit(e)

if args.action == "download":
device.download_bitstream(args.bitstream.read())
if args.action == "test":
if args.mode == "toggle-io":
device.download_bitstream(TestToggleIO().get_bitstream(debug=True))
device.set_voltage("AB", 3.3)
if args.mode == "expose-i2c":
device.download_bitstream(TestExposeI2C().get_bitstream(debug=True))
device.set_voltage("A", 3.3)
if args.action == "voltage":
if args.voltage is not None:
device.reset_alert(args.ports)
device.poll_alert() # clear any remaining alerts
device.set_voltage(args.ports, args.voltage)
if args.set_alert and args.voltage != 0.0:
time.sleep(0.050) # let the output capacitor discharge a bit
tolerance = args.tolerance / 100
low_volts = args.voltage * (1 - tolerance)
high_volts = args.voltage * (1 + tolerance)
device.set_alert(args.ports, low_volts, high_volts)

print("Port\tVio\tVsense\tRange")
alerts = device.poll_alert()
for port in args.ports:
vio = device.get_voltage(port)
vsense = device.measure_voltage(port)
alert = device.get_alert(port)
if port in alerts:
notice = " (ALERT)"
else:
notice = ""
print("{}\t{:.2}\t{:.3}\t{:.2}-{:.2}{}"
.format(port, vio, vsense, alert[0], alert[1], notice))

if args.action == "download":
device.download_bitstream(args.bitstream.read())

if args.action == "test":
if args.mode == "toggle-io":
device.download_bitstream(TestToggleIO().get_bitstream(debug=True))
device.set_voltage("AB", 3.3)
if args.mode == "expose-i2c":
device.download_bitstream(TestExposeI2C().get_bitstream(debug=True))
device.set_voltage("A", 3.3)

except FX2DeviceError as e:
raise SystemExit(e)


if __name__ == "__main__":
Expand Down
5 changes: 4 additions & 1 deletion software/glasgow/device.py
Expand Up @@ -166,7 +166,7 @@ def measure_voltage(self, spec):
except usb1.USBErrorPipe:
raise GlasgowDeviceError("Cannot measure port {} sense voltage".format(spec))

def set_alert(self, spec, low_volts=0.0, high_volts=5.5):
def set_alert(self, spec, low_volts, high_volts):
low_millivolts = round(low_volts * 1000)
high_millivolts = round(high_volts * 1000)
self.control_write(usb1.REQUEST_TYPE_VENDOR, REQ_ALERT_VOLT,
Expand All @@ -178,6 +178,9 @@ def set_alert(self, spec, low_volts=0.0, high_volts=5.5):
.format(spec or "(none)",
float(low_volts), float(high_volts)))

def reset_alert(self, spec):
self.set_alert(spec, 0.0, 5.5)

def get_alert(self, spec):
try:
low_millivolts, high_millivolts = struct.unpack("<HH",
Expand Down

0 comments on commit ad62d88

Please sign in to comment.