Add first pianohat plugin version

This commit is contained in:
Simon Stürz 2018-07-02 12:26:26 +02:00
parent ee48fdf247
commit c9dbf78cde
13 changed files with 918 additions and 0 deletions

16
debian/control vendored
View File

@ -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

View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginpianohat.so

View File

@ -40,6 +40,7 @@ PLUGIN_DIRS = \
keba \
remotessh \
dweetio \
pianohat \
CONFIG+=all

View 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));
}

View 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

View 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"
}
]
}
]
}
]
}
]
}

Binary file not shown.

74
pianohat/pianohat.cpp Normal file
View 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
View 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
View 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
View 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
View 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

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
</TS>