Skip to content

Commit

Permalink
Add MateControllerDevice base class for interfacing with devices atta…
Browse files Browse the repository at this point in the history
…ched to a MATE bus
  • Loading branch information
jorticus committed May 29, 2019
1 parent 5ad45bc commit 4d56353
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 29 deletions.
60 changes: 43 additions & 17 deletions examples/DeviceScan/DeviceScan.ino
Expand Up @@ -4,12 +4,22 @@
#include <uMate.h>
#include <Serial9b.h>

class MxDeviceController : public MateControllerDevice {
public:
MxDeviceController(MateControllerProtocol& protocol)
: MateControllerDevice(protocol, DeviceType::Mx)
{ }
};

//MateControllerProtocol mate_bus(Serial9b1, &Serial); // (HardwareSerial9b, Debug Serial)
MateControllerProtocol mate_bus(Serial9b1);

MxDeviceController mx_device(mate_bus);

DeviceType devices[10] = { DeviceType::None };

bool devicesFound = false;
bool mx_device_available = false;

const char* dtypes[] = {
"None",
Expand Down Expand Up @@ -41,23 +51,18 @@ void loop() {
// TODO: Read device revision
if (!devicesFound) {
Serial.println("Scanning for MATE devices...");
auto root_dtype = mate_bus.scan(0);
if (root_dtype != DeviceType::None) {
devices[0] = root_dtype;
Serial.print("0: ");
print_dtype(root_dtype);
Serial.println();
mate_bus.scan_ports();

if (mate_bus.scan(0) != DeviceType::None) {

if (root_dtype == DeviceType::Hub) {
for (int i = 1; i < 10; i++) {
auto dtype = mate_bus.scan(i);
if (dtype != DeviceType::None) {
devices[i] = dtype;
Serial.print(i);
Serial.print(": ");
print_dtype(dtype);
Serial.println();
}
for (int i = 0; i < NUM_PORTS; i++) {
DeviceType dtype = mate_bus.scan(i);
if (dtype != DeviceType::None) {
devices[i] = dtype;
Serial.print(i);
Serial.print(": ");
print_dtype(dtype);
Serial.println();
}
}

Expand All @@ -68,8 +73,29 @@ void loop() {
}

delay(1000);

Serial.println();
Serial.println("Scanning for MX device...");
int8_t port = mate_bus.find_device(DeviceType::Mx);
if (port == -1 || !mx_device.begin(port)) {
Serial.println("MX device not found!");
devicesFound = false;
} else {
// TODO: Revision is displayed wrong.
auto rev = mx_device.get_revision();
Serial.print("MX device found on port ");
Serial.print(port);
Serial.print(" Rev:");
Serial.print(rev.a); Serial.print(".");
Serial.print(rev.b); Serial.print(".");
Serial.print(rev.c);
Serial.println();
mx_device_available = true;
}
}
else {
// TODO: Query MX status
if (mx_device_available) {
//mx_device.query();
}
}
}
50 changes: 50 additions & 0 deletions src/MateControllerDevice.h
@@ -0,0 +1,50 @@
#ifndef MATE_CONTROLLER_DEVICE_H
#define MATE_CONTROLLER_DEVICE_H

class MateControllerDevice {
public:
MateControllerDevice(
MateControllerProtocol& protocol,
DeviceType dtype
) :
protocol(protocol),
dtype(dtype),
port(-1),
is_open(false)
{ }

// Open a device on the specified port.
// returns false if the device is not present on that port.
bool begin(uint8_t port) {
is_open = (protocol.scan(port) == dtype);
return is_open;
}

// Query a register and retrieve its value (BLOCKING)
// reg: The register address
// param: Optional parameter
// returns: The register value
uint16_t query(uint16_t reg, uint16_t param = 0) {
return protocol.query(reg, param, this->port);
}

// Control something (BLOCKING)
// reg: The control address
// value: The value to use for controlling (eg. disable/enable)
void control(uint16_t reg, uint16_t value) {
protocol.control(reg, value, this->port);
}

// Read the revision from the target device
revision_t get_revision() {
protocol.get_revision(this->port);
}

protected:
MateControllerProtocol& protocol;
DeviceType dtype;
int8_t port;
bool is_open;
};

#endif /* MATE_CONTROLLER_DEVICE_H */
50 changes: 46 additions & 4 deletions src/MateControllerProtocol.cpp
Expand Up @@ -100,16 +100,58 @@ bool MateControllerProtocol::control(uint16_t reg, uint16_t value, uint8_t port)
return true;
}

void MateControllerProtocol::scan_ports()
{
// Clear existing devices
devices_scanned = false;
for (int i = 0; i < NUM_PORTS; i++) {
devices[i] = DeviceType::None;
}

DeviceType root_dtype = scan(0);
devices[0] = root_dtype;

if (root_dtype == DeviceType::Hub) {
for (int i = 1; i < NUM_PORTS; i++) {
devices[i] = scan(i);
}
}

devices_scanned = true;
}

DeviceType MateControllerProtocol::scan(uint8_t port)
{
int16_t value = query(0x00, 0, port);
if (value >= 0 && value < DeviceType::MaxDevices) {
return (DeviceType)value;
if (port > NUM_PORTS)
return DeviceType::None;

if (devices_scanned) {
return devices[port];
}
else {
int16_t value = query(0x00, 0, port);
if (value >= 0 && value < DeviceType::MaxDevices) {
return (DeviceType)value;
}
return DeviceType::None;
}
return DeviceType::None;
}

int8_t MateControllerProtocol::find_device(DeviceType dtype)
{
// Use cached devices
if (!devices_scanned) {
scan_ports();
}

for (int i = 0; i < NUM_PORTS; i++) {
if (devices[i] == dtype) {
return i;
}
}

return -1; // Not found.
}

revision_t MateControllerProtocol::get_revision(uint8_t port)
{
Expand Down
29 changes: 24 additions & 5 deletions src/MateControllerProtocol.h
@@ -1,7 +1,10 @@
#ifndef MATE_H
#define MATE_H
#ifndef MATE_CONTROLLER_PROTOCOL_H
#define MATE_CONTROLLER_PROTOCOL_H

#include "uMate.h"
#include <Serial9b.h>

#define NUM_PORTS (10)

typedef struct {
uint16_t a;
Expand Down Expand Up @@ -53,11 +56,14 @@ class MateControllerProtocol : public MateNetPort
{
public:
MateControllerProtocol(HardwareSerial9b& ser, Stream* debug = nullptr)
: MateNetPort(ser, debug), timeout(100)
: MateNetPort(ser, debug), timeout(100), devices_scanned(false)
{ }

void set_timeout(int timeoutMillisec);

// Scan for all devices attached to the MATE bus (BLOCKING)
void scan_ports();

void send_packet(uint8_t port, packet_t* packet);
bool recv_response(OUT uint8_t* for_command, OUT response_t* response);
bool recv_response_blocking(OUT uint8_t* for_command, OUT response_t* response);
Expand All @@ -76,16 +82,29 @@ class MateControllerProtocol : public MateNetPort
// returns: true if control was successfully activated
bool control(uint16_t reg, uint16_t value, uint8_t port = 0);

// Scan for a device attached to the specified port (BLOCKING)

// Scan for a device attached to the specified port
// May use cached value in scan_ports()
// port: The port to scan, 0-10 (root: 0)
// returns: The type of device that is attached
DeviceType scan(uint8_t port = 0);

// Return the port that a device is attached to.
// May call scan_ports() and cache the result.
// dtype: The device type to look for
// returns: The port number, or -1 if not found.
int8_t find_device(DeviceType dtype);

// Read the revision from the target device
revision_t get_revision(uint8_t port = 0);

private:
int timeout;
DeviceType devices[NUM_PORTS];
bool devices_scanned;
};

#endif /* MATE_H */
// TODO: Unsure why I can only compile this by including it here...
#include "MateControllerDevice.h"

#endif /* MATE_CONTROLLER_PROTOCOL_H */
6 changes: 3 additions & 3 deletions src/MateDeviceProtocol.h
@@ -1,5 +1,5 @@
#ifndef MATE_DEVICE_H
#define MATE_DEVICE_H
#ifndef MATE_DEVICE_PROTOCOL_H
#define MATE_DEVICE_PROTOCOL_H

#include "uMate.h"

Expand All @@ -22,4 +22,4 @@ class MateDeviceProtocol : public MateNetPort
};


#endif /* MATE_DEVICE_H */
#endif /* MATE_DEVICE_PROTOCOL_H */
2 changes: 2 additions & 0 deletions src/uMate.h
Expand Up @@ -11,6 +11,8 @@

#include "MateNetPort.h"
#include "MateControllerProtocol.h"
//#include "MateControllerDevice.h" // TODO: This doesn't compile here...
#include "MateDeviceProtocol.h"


#endif /* UMATE_H */

0 comments on commit 4d56353

Please sign in to comment.