Documenting for publication
This commit is contained in:
parent
6999e35a91
commit
89610a3568
2 changed files with 98 additions and 70 deletions
|
@ -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 # => <PiRef XXX-01>
|
||||
hat.max_pi # => <PiRef XXX-05>
|
||||
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(<int | PiRef>)
|
||||
hat.power_off(<int | PiRef>)
|
||||
hat.power_status(<int | PiRef>)
|
||||
|
||||
hat.power_all_off()
|
||||
hat.power_all_on()
|
||||
|
||||
hat.eeprom_save_powerstate()
|
||||
```
|
||||
|
||||
### Board identification
|
||||
|
||||
``` python
|
||||
hat.get_order()
|
||||
hat.set_order(<order: uint8>)
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue