From 89610a3568e1d96d6fea50daad14e966b3566fd6 Mon Sep 17 00:00:00 2001 From: Reid 'arrdem' McKenzie Date: Fri, 5 Nov 2021 12:18:45 -0600 Subject: [PATCH] Documenting for publication --- projects/clusterctrl/README.md | 103 +++++++++++++++++- .../src/python/clusterctrl/xra1200.py | 65 ----------- 2 files changed, 98 insertions(+), 70 deletions(-) delete mode 100644 projects/clusterctrl/src/python/clusterctrl/xra1200.py diff --git a/projects/clusterctrl/README.md b/projects/clusterctrl/README.md index 7710fa7..d2008ec 100644 --- a/projects/clusterctrl/README.md +++ b/projects/clusterctrl/README.md @@ -1,13 +1,106 @@ # clusterctrl -This project is a rewrite of the `clusterctrl` tool provided by the 8086 consultancy for interacting with their ClusterCTRL and ClusterHAT line of Raspberry Pi backplane products. +This project is a clean-sheet rewrite of the `clusterctrl` tool and underlying device driver provided by the 8086 consultancy for interacting with their ClusterCTRL and ClusterHAT line of Raspberry Pi backplane products. -It serves to factor out the underlying i²c driver common to the ClusterCTRL family of products, and aims to implement a far more idiomatic and better documented and far more consistent CLI tool. +## Usage & driver API + +``` python +from clusterctrl.driver import ClusterCTRLv2Driver as Driver +from smbus2 import SMBus + +hat = Driver(SMBus(3)) # Note that 3 here is the number of the i2c device the HAT is on +``` + +A quick API overview - + +The CTRL/HAT products "order" themselves (identify boards) using an EEPROM stored value called 'order'. +The official clients use "order" to enable for somewhat stable sequential addressing of "pi6" as being board 2 pi 1. +However it's far more general purpose and predictable to directly expose and model the device tree. + +Note that the firmware default for "order" is `20` and this driver will automatically assign random IDs to boards with orders of 20. +This behavior can be disabled by subclassing the driver and overloading `_post_init()`. + +This API is built atop a `PiRef(board_id, pi_id)` tuple which is intended to allow for the construction of cluster management APIs which allow for automatic but predictable mapping of requests (eg. `power_on`, `power_status`) to a given device. + +``` python +hat.fw_version # => (1, 6) +hat.min_pi # => +hat.max_pi # => +hat.pis() # => Iterable[PiRef] (iterate over all Pis on this device in order) +hat.type # => BoardType +hat.max_adc # => int (ADC support is incomplete) +``` + +### Power status + +``` +hat.power_on() +hat.power_off() +hat.power_status() + +hat.power_all_off() +hat.power_all_on() + +hat.eeprom_save_powerstate() +``` + +### Board identification + +``` python +hat.get_order() +hat.set_order() + +hat.eeprom_save_order() +``` + +### Alert lights + +``` python +hat.alert_on() +hat.alert_off() + +hat.led_on() +hat.led_off() + +hat.eeprom_save_leds() +``` + +### Fan control + +``` python +hat.fan_on() +hat.fan_off() +hat.fan_status() + +hat.read_temp() # Temp in integer kelvin +``` + +### USB hub control + +``` python +hat.hub_on() +hat.hub_off() +hat.hub_reset() +``` + +### USB booting + +``` python +hat.usbboot_on() +hat.usbboot_off() +hat.usbboot_status() +hat.eeprom_save_usbboot() +``` + +#### Driver.eeprom_reset +Reset all EEPROM stored settings to their 'factory' firmware defaults. + +#### Driver.eeprom_save_all +Save all values back to EEPROM. +Note that this does not update the defaults restored by `Driver.eeprom_reset`. ## license -Copyright (c) 2018 Chris Burton (8086 consultancy) Copyright (c) 2021 Reid McKenzie -This software is published under the MIT License - +This software is published under the terms of the MIT License diff --git a/projects/clusterctrl/src/python/clusterctrl/xra1200.py b/projects/clusterctrl/src/python/clusterctrl/xra1200.py deleted file mode 100644 index 5185ffb..0000000 --- a/projects/clusterctrl/src/python/clusterctrl/xra1200.py +++ /dev/null @@ -1,65 +0,0 @@ -import smbus - - -# Registers -# Direction -IN = 0x00 -OUT = 0x01 -DIR = 0x03 -PUR = 0x04 - -INPUT = 1 -OUTPUT = 0 - - -class Xra1200: - bus = -1 - address = -1 - port = -1 - - def __init__(self, bus=0, address=0x39, port=0, dir="Null"): - self.bus = smbus.SMBus(bus) - self.address = address - self.port = port - if dir == 1: - self.set_input() - elif dir == 0: - self.set_output() - - def set_dir(self, dir): - self.bus.write_byte_data(self.address, DIR, dir) - - def get_dir(self): - return self.bus.read_byte_data(self.address, DIR) - - def set_pur(self, pur): - self.bus.write_byte_data(self.address, PUR, pur) - - def get_pur(self): - try: - reg = self.bus.read_byte_data(self.address, PUR) - except IOError as err: - return -1 - return reg - - def set_input(self): - state = self.bus.read_byte_data(self.address, DIR) - self.bus.write_byte_data(self.address, DIR, state | 1 << self.port) - - def write_byte(self, data): - self.bus.write_byte_data(self.address, OUT, data) - - def read_byte(self): - return self.bus.read_byte_data(self.address, IN) - - def on(self): - state = self.bus.read_byte_data(self.address, OUT) - self.bus.write_byte_data(self.address, OUT, state | 1 << self.port) - - def off(self): - state = self.bus.read_byte_data(self.address, OUT) - self.bus.write_byte_data(self.address, OUT, state & (255 - (1 << self.port))) - - def get(self): - state = self.bus.read_byte_data(self.address, IN) - return (state >> self.port) & 1