mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-17 00:36:35 +02:00
Add first pianohat plugin version
This commit is contained in:
parent
ee48fdf247
commit
c9dbf78cde
16
debian/control
vendored
16
debian/control
vendored
@ -632,6 +632,21 @@ Description: nymea.io plugin for remote ssh connection
|
||||
.
|
||||
This package will install the nymea.io plugin for remote ssh connection
|
||||
|
||||
Package: nymea-plugin-pianohat
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
nymea-plugins-translations,
|
||||
Description: nymea.io plugin for the Raspberry Pi Pianohat
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
server works like a translator for devices, things and services and
|
||||
allows them to interact.
|
||||
With the powerful rule engine you are able to connect any device available
|
||||
in the system and create individual scenes and behaviors for your environment.
|
||||
.
|
||||
This package will install the nymea.io plugin for the Raspberry Pi Pianohat
|
||||
|
||||
|
||||
|
||||
Package: nymea-plugins-translations
|
||||
Section: misc
|
||||
@ -670,6 +685,7 @@ Depends: nymea-plugin-awattar,
|
||||
nymea-plugin-elgato,
|
||||
nymea-plugin-senic,
|
||||
nymea-plugin-keba,
|
||||
nymea-plugin-pianohat,
|
||||
Replaces: guh-plugins
|
||||
Description: Plugins for nymea IoT server - the default plugin collection
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
|
||||
1
debian/nymea-plugin-pianohat.install.in
vendored
Normal file
1
debian/nymea-plugin-pianohat.install.in
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginpianohat.so
|
||||
@ -40,6 +40,7 @@ PLUGIN_DIRS = \
|
||||
keba \
|
||||
remotessh \
|
||||
dweetio \
|
||||
pianohat \
|
||||
|
||||
|
||||
CONFIG+=all
|
||||
|
||||
166
pianohat/devicepluginpianohat.cpp
Normal file
166
pianohat/devicepluginpianohat.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "plugininfo.h"
|
||||
#include "devicepluginpianohat.h"
|
||||
#include "types/param.h"
|
||||
|
||||
DevicePluginPianohat::DevicePluginPianohat()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginPianohat::init()
|
||||
{
|
||||
// Initialize/create objects
|
||||
}
|
||||
|
||||
void DevicePluginPianohat::startMonitoringAutoDevices()
|
||||
{
|
||||
// Start seaching for devices which can be discovered and added automatically
|
||||
}
|
||||
|
||||
void DevicePluginPianohat::postSetupDevice(Device *device)
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Post setup device" << device->name() << device->params();
|
||||
|
||||
m_pianohat->enable();
|
||||
}
|
||||
|
||||
void DevicePluginPianohat::deviceRemoved(Device *device)
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Remove device" << device->name() << device->params();
|
||||
|
||||
// Clean up all data related to this device
|
||||
if (m_pianohat) {
|
||||
m_pianohat->disable();
|
||||
m_pianohat->deleteLater();
|
||||
m_pianohat = nullptr;
|
||||
}
|
||||
|
||||
if (m_device) {
|
||||
// Note: the DeviceManager will take care about the device Object
|
||||
m_device = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceManager::DeviceSetupStatus DevicePluginPianohat::setupDevice(Device *device)
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Setup device" << device->name() << device->params();
|
||||
|
||||
// Make sure there is not already a pianohat added, since only one device is supported
|
||||
if (m_pianohat) {
|
||||
qCWarning(dcPianohat()) << "There has already been setup a PianoHat. Only one instance of this device is allowed.";
|
||||
return DeviceManager::DeviceSetupStatusFailure;
|
||||
}
|
||||
|
||||
// Create the PianoHat object and store the device pointer (there can always be only one pianohat)
|
||||
m_device = device;
|
||||
m_pianohat = new PianoHat(this);
|
||||
connect(m_pianohat, &PianoHat::keyPressed, this, &DevicePluginPianohat::onPianohatKeyPressed);
|
||||
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceError DevicePluginPianohat::executeAction(Device *device, const Action &action)
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Executing action for device" << device->name() << action.actionTypeId().toString() << action.params();
|
||||
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
}
|
||||
|
||||
void DevicePluginPianohat::onPianohatKeyPressed(const PianoHat::Key &key, bool pressed)
|
||||
{
|
||||
qCDebug(dcPianohat()) << key << (pressed ? "pressed" : "released");
|
||||
|
||||
// Emit the key pressed event on pressed and set the bool states
|
||||
ParamList eventParams;
|
||||
switch (key) {
|
||||
case PianoHat::KeyC:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "C"));
|
||||
m_device->setStateValue(pianohatCStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyCSharp:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "C#"));
|
||||
m_device->setStateValue(pianohatCSharpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyD:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "D"));
|
||||
m_device->setStateValue(pianohatDStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyDSharp:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "D#"));
|
||||
m_device->setStateValue(pianohatDSharpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyE:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "E"));
|
||||
m_device->setStateValue(pianohatEStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyF:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "F#"));
|
||||
m_device->setStateValue(pianohatFStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyG:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "G"));
|
||||
m_device->setStateValue(pianohatGSharpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyGSharp:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "G#"));
|
||||
m_device->setStateValue(pianohatGSharpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyA:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "A"));
|
||||
m_device->setStateValue(pianohatAStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyASharp:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "A#"));
|
||||
m_device->setStateValue(pianohatASharpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyB:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "B"));
|
||||
m_device->setStateValue(pianohatBStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyHighC:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "C (high)"));
|
||||
m_device->setStateValue(pianohatCHighStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyOctaveDown:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "Octave down"));
|
||||
m_device->setStateValue(pianohatOctaveDownStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyOctaveUp:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "Octave up"));
|
||||
m_device->setStateValue(pianohatOctaveUpStateTypeId, pressed);
|
||||
break;
|
||||
case PianoHat::KeyInstrument:
|
||||
eventParams.append(Param(pianohatButtonNameParamTypeId, "Instrument"));
|
||||
m_device->setStateValue(pianohatInstrumentStateTypeId, pressed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Only emit the pressed event if the button was touched
|
||||
if (!eventParams.isEmpty() && pressed)
|
||||
emitEvent(Event(pianohatPressedEventTypeId, m_device->id(), eventParams));
|
||||
|
||||
}
|
||||
58
pianohat/devicepluginpianohat.h
Normal file
58
pianohat/devicepluginpianohat.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEVICEPLUGINPIANOHAT_H
|
||||
#define DEVICEPLUGINPIANOHAT_H
|
||||
|
||||
#include "pianohat.h"
|
||||
#include "devicemanager.h"
|
||||
#include "plugin/deviceplugin.h"
|
||||
|
||||
class DevicePluginPianohat: public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginpianohat.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
|
||||
public:
|
||||
explicit DevicePluginPianohat();
|
||||
|
||||
void init() override;
|
||||
void startMonitoringAutoDevices() override;
|
||||
void postSetupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
|
||||
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
|
||||
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
|
||||
|
||||
private:
|
||||
Device *m_device = nullptr;
|
||||
PianoHat *m_pianohat = nullptr;
|
||||
|
||||
private slots:
|
||||
void onPianohatKeyPressed(const PianoHat::Key &key, bool pressed);
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINPIANOHAT_H
|
||||
190
pianohat/devicepluginpianohat.json
Normal file
190
pianohat/devicepluginpianohat.json
Normal file
@ -0,0 +1,190 @@
|
||||
{
|
||||
"name": "Pianohat",
|
||||
"displayName": "Pianohat",
|
||||
"id": "d2cbfd1e-2c4b-4ddd-8a37-21f4c07b9ab3",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "pimoroni",
|
||||
"displayName": "Pimoroni",
|
||||
"id": "3d1adc76-2867-4cbd-bdae-e2cf754869eb",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"name": "pianohat",
|
||||
"displayName": "PianoHat",
|
||||
"id": "8c0001dd-0cb5-4239-af0d-d2c3cb32a803",
|
||||
"deviceIcon": "None",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": ["User"],
|
||||
"interfaces": [ "simplemultibutton" ],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "b55ae3da-74b5-4419-b00c-296ed4d1be3b",
|
||||
"name": "c",
|
||||
"displayName": "C pressed",
|
||||
"displayNameEvent": "C pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "6ad62591-8f0f-4579-8185-92c29e5bb627",
|
||||
"name": "cSharp",
|
||||
"displayName": "C# pressed",
|
||||
"displayNameEvent": "C# pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "7713a612-5e85-4d56-84b4-33d528e39c99",
|
||||
"name": "d",
|
||||
"displayName": "D pressed",
|
||||
"displayNameEvent": "D pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "77b4628e-3965-4125-a927-80ddff868cab",
|
||||
"name": "dSharp",
|
||||
"displayName": "D# pressed",
|
||||
"displayNameEvent": "D# pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "5b350f53-cb79-4bb4-9355-8407634b88dc",
|
||||
"name": "e",
|
||||
"displayName": "E pressed",
|
||||
"displayNameEvent": "E pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "80432960-2fe8-423b-ab9b-a2b5dc71356c",
|
||||
"name": "f",
|
||||
"displayName": "F pressed",
|
||||
"displayNameEvent": "F pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "b0c8c1af-a311-4f37-a1a8-bd734e540a6b",
|
||||
"name": "fSharp",
|
||||
"displayName": "F# pressed",
|
||||
"displayNameEvent": "F# pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "2eb0a67f-d370-4b79-9c84-48b544c77004",
|
||||
"name": "g",
|
||||
"displayName": "G pressed",
|
||||
"displayNameEvent": "G pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "1897f604-cb26-4d66-b292-251f59b27f56",
|
||||
"name": "gSharp",
|
||||
"displayName": "G# pressed",
|
||||
"displayNameEvent": "G# pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "5ff7377c-95f2-4080-be0c-145b94437ee6",
|
||||
"name": "a",
|
||||
"displayName": "A pressed",
|
||||
"displayNameEvent": "A pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "b221e069-4cbd-4dcd-adba-97beb6630211",
|
||||
"name": "aSharp",
|
||||
"displayName": "A# pressed",
|
||||
"displayNameEvent": "A# pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "99324edb-e88e-4f1d-96c7-49caf861cd4b",
|
||||
"name": "b",
|
||||
"displayName": "B pressed",
|
||||
"displayNameEvent": "B pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "3bc73c73-81ec-41d5-ae77-471d3399740b",
|
||||
"name": "cHigh",
|
||||
"displayName": "C (high) pressed",
|
||||
"displayNameEvent": "C (high) pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "b890db7f-9c60-4288-8911-160d4f4ea508",
|
||||
"name": "octaveDown",
|
||||
"displayName": "Octave down pressed",
|
||||
"displayNameEvent": "Octave down pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "a32bf226-ca2f-48cf-9834-e55b33fd0e58",
|
||||
"name": "octaveUp",
|
||||
"displayName": "Octave up pressed",
|
||||
"displayNameEvent": "Octave up pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "77e47139-445c-4a88-a266-ddefd22997c2",
|
||||
"name": "instrument",
|
||||
"displayName": "Instrument pressed",
|
||||
"displayNameEvent": "Octave down pressed changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "4877964c-951f-42d7-9775-bf28615700b1",
|
||||
"name": "pressed",
|
||||
"displayName": "Key pressed",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "74bf5392-d71e-45a0-a96b-8b4ec405d3dd",
|
||||
"name": "buttonName",
|
||||
"displayName": "Key",
|
||||
"type": "QString",
|
||||
"allowedValues": [
|
||||
"C",
|
||||
"C#",
|
||||
"D",
|
||||
"D#",
|
||||
"E",
|
||||
"F",
|
||||
"F#",
|
||||
"G",
|
||||
"G#",
|
||||
"A",
|
||||
"A#",
|
||||
"B",
|
||||
"C (high)",
|
||||
"Octave down",
|
||||
"Octave up",
|
||||
"Instrument"
|
||||
],
|
||||
"defaultValue": "C"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
pianohat/docs/CAP1188-datasheet.pdf
Normal file
BIN
pianohat/docs/CAP1188-datasheet.pdf
Normal file
Binary file not shown.
74
pianohat/pianohat.cpp
Normal file
74
pianohat/pianohat.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "pianohat.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
PianoHat::PianoHat(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Create touch sensor from main trhead" << QThread::currentThreadId();
|
||||
|
||||
/* Note: the pianohat has 2 CAP1188 chips on following Addresses
|
||||
* https://pinout.xyz/pinout/piano_hat#
|
||||
* - Register 0x28
|
||||
* - Alert GPIO: 4
|
||||
* - Reset GPIO: 17
|
||||
* - Register 0x2b
|
||||
* - Alert GPIO: 27
|
||||
* - Reset GPIO: 22
|
||||
*/
|
||||
|
||||
m_sensorOne = new TouchSensor(0x28, 4, 17, this);
|
||||
connect(m_sensorOne, &TouchSensor::keyPressedChanged, this, &PianoHat::onSensorOneKeyPressedChanged);
|
||||
|
||||
m_sensorTwo = new TouchSensor(0x2b, 27, 22, this);
|
||||
connect(m_sensorTwo, &TouchSensor::keyPressedChanged, this, &PianoHat::onSensorTwoKeyPressedChanged);
|
||||
}
|
||||
|
||||
void PianoHat::enable()
|
||||
{
|
||||
// Enable the sensors
|
||||
m_sensorOne->enableSensor();
|
||||
m_sensorTwo->enableSensor();
|
||||
}
|
||||
|
||||
void PianoHat::disable()
|
||||
{
|
||||
// Enable the sensors
|
||||
m_sensorOne->disableSensor();
|
||||
m_sensorTwo->disableSensor();
|
||||
}
|
||||
|
||||
void PianoHat::onSensorOneKeyPressedChanged(quint8 key, bool pressed)
|
||||
{
|
||||
// Map the bit number to the actual pianohat key
|
||||
Key pianoHatKey = static_cast<Key>(key);
|
||||
emit keyPressed(pianoHatKey, pressed);
|
||||
}
|
||||
|
||||
void PianoHat::onSensorTwoKeyPressedChanged(quint8 key, bool pressed)
|
||||
{
|
||||
// Map the bit number to the actual pianohat key (bit + 8)
|
||||
Key pianoHatKey = static_cast<Key>(key + 8);
|
||||
emit keyPressed(pianoHatKey, pressed);
|
||||
}
|
||||
76
pianohat/pianohat.h
Normal file
76
pianohat/pianohat.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef PIANOHAT_H
|
||||
#define PIANOHAT_H
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "touchsensor.h"
|
||||
#include "plugin/device.h"
|
||||
|
||||
|
||||
class PianoHat : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Key {
|
||||
// Sensor one 0x28
|
||||
KeyC = 0,
|
||||
KeyCSharp = 1,
|
||||
KeyD = 2,
|
||||
KeyDSharp = 3,
|
||||
KeyE = 4,
|
||||
KeyF = 5,
|
||||
KeyFSharp = 6,
|
||||
KeyG = 7,
|
||||
// Sensor two 0x2b
|
||||
KeyGSharp = 8,
|
||||
KeyA = 9,
|
||||
KeyASharp = 10,
|
||||
KeyB = 11,
|
||||
KeyHighC = 12,
|
||||
KeyOctaveDown = 13,
|
||||
KeyOctaveUp = 14,
|
||||
KeyInstrument = 15
|
||||
};
|
||||
Q_ENUM(Key)
|
||||
|
||||
explicit PianoHat(QObject *parent = nullptr);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
private:
|
||||
TouchSensor *m_sensorOne = nullptr;
|
||||
TouchSensor *m_sensorTwo = nullptr;
|
||||
|
||||
signals:
|
||||
void keyPressed(const Key &key, bool pressed);
|
||||
|
||||
private slots:
|
||||
void onSensorOneKeyPressedChanged(quint8 key, bool pressed);
|
||||
void onSensorTwoKeyPressedChanged(quint8 key, bool pressed);
|
||||
|
||||
};
|
||||
|
||||
#endif // PIANOHAT_H
|
||||
14
pianohat/pianohat.pro
Normal file
14
pianohat/pianohat.pro
Normal file
@ -0,0 +1,14 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_devicepluginpianohat)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginpianohat.cpp \
|
||||
pianohat.cpp \
|
||||
touchsensor.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginpianohat.h \
|
||||
pianohat.h \
|
||||
touchsensor.h
|
||||
|
||||
221
pianohat/touchsensor.cpp
Normal file
221
pianohat/touchsensor.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "touchsensor.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "linux/i2c-dev.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
TouchSensor::TouchSensor(quint8 i2cRegister, int interruptGpio, int resetGpio, QObject *parent) :
|
||||
QThread(parent),
|
||||
m_i2cRegister(i2cRegister),
|
||||
m_interruptGpioPin(interruptGpio),
|
||||
m_resetGpioPin(resetGpio)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TouchSensor::~TouchSensor()
|
||||
{
|
||||
disableSensor();
|
||||
wait();
|
||||
}
|
||||
|
||||
void TouchSensor::setupGpios()
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Setup GPIOs for sensor" << QString().number(m_i2cRegister, 16).prepend("0x");
|
||||
|
||||
// Init reset gpio
|
||||
m_resetGpio = new Gpio(m_resetGpioPin);
|
||||
if (!m_resetGpio->exportGpio()) {
|
||||
qCWarning(dcPianohat()) << "Could not export reset GPIO" << m_resetGpioPin;
|
||||
}
|
||||
|
||||
msleep(500);
|
||||
|
||||
if (!m_resetGpio->setDirection(Gpio::DirectionOutput)) {
|
||||
qCWarning(dcPianohat()) << "Could not set direction of reset GPIO" << m_resetGpioPin;
|
||||
}
|
||||
|
||||
m_resetGpio->moveToThread(this);
|
||||
}
|
||||
|
||||
void TouchSensor::initializeSensor()
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Start initializing sensor" << QString().number(m_i2cRegister, 16).prepend("0x");
|
||||
|
||||
// Reset the controller
|
||||
qCDebug(dcPianohat()) << "Reset sensor" << QString().number(m_i2cRegister, 16).prepend("0x");
|
||||
m_resetGpio->setValue(Gpio::ValueLow);
|
||||
msleep(100);
|
||||
m_resetGpio->setValue(Gpio::ValueHigh);
|
||||
msleep(100);
|
||||
m_resetGpio->setValue(Gpio::ValueLow);
|
||||
msleep(100);
|
||||
|
||||
// Configure sensor
|
||||
qCDebug(dcPianohat()) << "Setup sensor" << QString().number(m_i2cRegister, 16).prepend("0x");
|
||||
|
||||
m_i2cDevice = open(m_deviceFile.toLocal8Bit(), O_RDWR);
|
||||
if(m_i2cDevice < 0){
|
||||
qCWarning(dcPianohat()) << "Could not open I2C device" << m_deviceFile;
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = ioctl(m_i2cDevice, I2C_SLAVE, m_i2cRegister);
|
||||
if (ret < 0) {
|
||||
qCWarning(dcPianohat()) << "Failed to aquire slave mode access to I2C device";
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcPianohat()) << "--> Product ID:" << QString().number(readRegister(CAP1188_PROUCT_ID), 16).prepend("0x");
|
||||
qCDebug(dcPianohat()) << "--> Manufacturer ID:" << QString().number(readRegister(CAP1188_MANUFACTURER_ID), 16).prepend("0x");
|
||||
qCDebug(dcPianohat()) << "--> Revision:" << QString().number(readRegister(CAP1188_REVISION), 16).prepend("0x");
|
||||
|
||||
// Enable all inputs
|
||||
writeRegister(CAP1188_INPUT_ENABLE, 0xFF);
|
||||
|
||||
// Enable interrupts
|
||||
writeRegister(0x27, 0xFF);
|
||||
|
||||
// Disable repeat
|
||||
writeRegister(0x28, 0x00);
|
||||
|
||||
// Enable multitouch
|
||||
quint8 multitouchConfig = readRegister(CAP1188_MULTITOUCH_CONFIG);
|
||||
writeRegister(CAP1188_MULTITOUCH_CONFIG, multitouchConfig & ~0x80);
|
||||
|
||||
// Sampling config
|
||||
// Note: configurations from: https://github.com/pimoroni/cap1xxx/blob/master/library/cap1xxx.py#L305
|
||||
writeRegister(CAP1188_SAMPLING_CONFIG, 0b00001000); // 1sample per measure, 1.28ms time, 35ms cycle
|
||||
|
||||
// Sensitivity
|
||||
writeRegister(CAP1188_SENSITIVITY_CONFIG, 0b01100000); // 2x sensitivity
|
||||
|
||||
// General config
|
||||
writeRegister(CAP1188_GENERAL_CONFIG, 0b00111000);
|
||||
|
||||
// Config 2
|
||||
writeRegister(CAP1188_CONFIGURATION2, 0b01100000);
|
||||
|
||||
// Enable led for all keys
|
||||
writeRegister(CAP1188_LED, 0xFF);
|
||||
|
||||
// Speed up
|
||||
writeRegister(CAP1188_STANDBY_CONFIG, 0x30);
|
||||
}
|
||||
|
||||
void TouchSensor::cleanUp()
|
||||
{
|
||||
// Clean up
|
||||
if (m_resetGpio) {
|
||||
delete m_resetGpio;
|
||||
m_resetGpio = nullptr;
|
||||
}
|
||||
|
||||
if (m_i2cDevice > 0) {
|
||||
close(m_i2cDevice);
|
||||
m_i2cDevice = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void TouchSensor::run()
|
||||
{
|
||||
setupGpios();
|
||||
initializeSensor();
|
||||
|
||||
qCDebug(dcPianohat()) << "Initialized sensor" << QString().number(m_i2cRegister, 16).prepend("0x");
|
||||
|
||||
// Poll GPIO for interrupts
|
||||
while (1) {
|
||||
|
||||
quint8 inputStatus = readRegister(CAP1188_INPUTSTATUS);
|
||||
if (inputStatus) {
|
||||
processInputData(inputStatus);
|
||||
clearInterrupt();
|
||||
} else {
|
||||
processInputData(0);
|
||||
}
|
||||
|
||||
QMutexLocker locker(&m_stopMutex);
|
||||
if (m_stop) break;
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
qCDebug(dcPianohat()) << "Sensor thread finished.";
|
||||
}
|
||||
|
||||
quint8 TouchSensor::readRegister(quint8 i2cRegister)
|
||||
{
|
||||
i2c_smbus_write_byte(m_i2cDevice, i2cRegister);
|
||||
return i2c_smbus_read_byte(m_i2cDevice);;
|
||||
}
|
||||
|
||||
void TouchSensor::writeRegister(quint8 i2cRegister, quint8 value)
|
||||
{
|
||||
i2c_smbus_write_byte_data(m_i2cDevice, i2cRegister, value);
|
||||
}
|
||||
|
||||
void TouchSensor::clearInterrupt()
|
||||
{
|
||||
quint8 mainConfiguration = readRegister(CAP1188_MAIN);
|
||||
mainConfiguration &= ~0b00000001;
|
||||
writeRegister(CAP1188_MAIN, mainConfiguration);
|
||||
}
|
||||
|
||||
void TouchSensor::processInputData(quint8 data)
|
||||
{
|
||||
if (m_currentInputStatus != data) {
|
||||
//qCDebug(dcPianohat()) << "-->" << data;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bool keyPressed = data & (1 << i);
|
||||
bool previousStatus = m_currentInputStatus & (1 << i);
|
||||
if (previousStatus != keyPressed) {
|
||||
//qCDebug(dcPianohat()) << "Touched changed" << QString().number(m_i2cRegister, 16).prepend("0x") << " --> Key" << i << " = " << (keyPressed ? "pressed" : "released");
|
||||
emit keyPressedChanged(i, keyPressed);
|
||||
}
|
||||
}
|
||||
|
||||
m_currentInputStatus = data;
|
||||
}
|
||||
}
|
||||
|
||||
void TouchSensor::enableSensor()
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
void TouchSensor::disableSensor()
|
||||
{
|
||||
qCDebug(dcPianohat()) << "Disable sensor";
|
||||
QMutexLocker locker(&m_stopMutex);
|
||||
m_stop = true;
|
||||
}
|
||||
97
pianohat/touchsensor.h
Normal file
97
pianohat/touchsensor.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TOUCHSENSOR_H
|
||||
#define TOUCHSENSOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
// Registers of CAP1188 capacitive touch sensor (see doc folder for the datasheet)
|
||||
#define CAP1188_MAIN 0x00
|
||||
#define CAP1188_INPUTSTATUS 0x03
|
||||
#define CAP1188_GENERAL_CONFIG 0x20
|
||||
#define CAP1188_SENSITIVITY_CONFIG 0x1F
|
||||
#define CAP1188_INPUT_ENABLE 0x21
|
||||
#define CAP1188_SAMPLING_CONFIG 0x24
|
||||
#define CAP1188_MULTITOUCH_CONFIG 0x2A
|
||||
#define CAP1188_STANDBY_CONFIG 0x41
|
||||
#define CAP1188_CONFIGURATION2 0x44
|
||||
#define CAP1188_LED 0x72
|
||||
#define CAP1188_LEDPOL 0x73
|
||||
#define CAP1188_PROUCT_ID 0xFD
|
||||
#define CAP1188_MANUFACTURER_ID 0xFE
|
||||
#define CAP1188_REVISION 0xFF
|
||||
|
||||
class TouchSensor : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TouchSensor(quint8 i2cRegister, int interruptGpio, int resetGpio, QObject *parent = nullptr);
|
||||
~TouchSensor();
|
||||
|
||||
private:
|
||||
// Sensor wiring
|
||||
quint8 m_i2cRegister = 0x28;
|
||||
int m_interruptGpioPin = 4;
|
||||
int m_resetGpioPin = 17;
|
||||
|
||||
Gpio *m_resetGpio = nullptr;
|
||||
quint8 m_currentInputStatus = 0;
|
||||
|
||||
// I2C
|
||||
QString m_deviceFile = "/dev/i2c-1";
|
||||
int m_i2cDevice = -1;
|
||||
|
||||
// Thread stuff
|
||||
QMutex m_stopMutex;
|
||||
bool m_stop = false;
|
||||
void run() override;
|
||||
|
||||
// Setup methods
|
||||
void setupGpios();
|
||||
void initializeSensor();
|
||||
void cleanUp();
|
||||
|
||||
// I2C methods
|
||||
quint8 readRegister(quint8 i2cRegister);
|
||||
void writeRegister(quint8 i2cRegister, quint8 value);
|
||||
|
||||
// Sensor methods
|
||||
void clearInterrupt();
|
||||
void processInputData(quint8 data);
|
||||
|
||||
signals:
|
||||
void keyPressedChanged(int key, bool pressed);
|
||||
|
||||
|
||||
public slots:
|
||||
void enableSensor();
|
||||
void disableSensor();
|
||||
|
||||
};
|
||||
|
||||
#endif // TOUCHSENSOR_H
|
||||
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
</TS>
|
||||
Loading…
x
Reference in New Issue
Block a user