mirror of
https://github.com/dwhinham/mt32-pi.git
synced 2026-07-08 17:56:16 +00:00
WIP: Control surface via I2C port expander
This commit is contained in:
@@ -8,12 +8,14 @@ OBJS := src/main.o \
|
||||
src/kernel.o \
|
||||
src/config.o \
|
||||
src/mt32synth.o \
|
||||
src/control/mcp23017.o \
|
||||
src/lcd/hd44780.o \
|
||||
src/lcd/hd44780fourbit.o \
|
||||
src/lcd/hd44780i2c.o \
|
||||
src/lcd/ssd1306.o
|
||||
|
||||
EXTRACLEAN += src/*.d src/*.o \
|
||||
src/control/*.d src/control/*.o \
|
||||
src/lcd/*.d src/lcd/*.o
|
||||
|
||||
#
|
||||
|
||||
46
include/control/mcp23017.h
Normal file
46
include/control/mcp23017.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// mcp23017.h
|
||||
//
|
||||
// mt32-pi - A bare-metal Roland MT-32 emulator for Raspberry Pi
|
||||
// Copyright (C) 2020 Dale Whinham <daleyo@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#ifndef _mcp23017_h
|
||||
#define _mcp23017_h
|
||||
|
||||
#include <circle/i2cmaster.h>
|
||||
#include <circle/types.h>
|
||||
|
||||
class CMCP23017
|
||||
{
|
||||
public:
|
||||
CMCP23017(CI2CMaster* pI2CMaster, u8 pAddress = 0x20);
|
||||
|
||||
bool Initialize();
|
||||
void Update();
|
||||
|
||||
private:
|
||||
u8 Read(u8 pRegister);
|
||||
void Write(u8 pRegister, u8 pValue);
|
||||
|
||||
CI2CMaster* mI2CMaster;
|
||||
u8 mAddress;
|
||||
|
||||
u8 mPortAPrevState;
|
||||
u8 mPortBPrevState;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "control/mcp23017.h"
|
||||
#include "lcd/clcd.h"
|
||||
#include "config.h"
|
||||
#include "mt32synth.h"
|
||||
@@ -57,6 +58,7 @@ protected:
|
||||
|
||||
CI2CMaster mI2CMaster;
|
||||
CCharacterLCD* mLCD;
|
||||
CMCP23017* mControl;
|
||||
|
||||
private:
|
||||
bool InitPCM51xx(u8 pAddress);
|
||||
|
||||
89
src/control/mcp23017.cpp
Normal file
89
src/control/mcp23017.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// mcp23017.cpp
|
||||
//
|
||||
// mt32-pi - A bare-metal Roland MT-32 emulator for Raspberry Pi
|
||||
// Copyright (C) 2020 Dale Whinham <daleyo@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include <circle/logger.h>
|
||||
|
||||
#include "control/mcp23017.h"
|
||||
|
||||
#define MCP_IODIRA 0x00
|
||||
#define MCP_IODIRB 0x01
|
||||
#define MCP_IPOLA 0x02
|
||||
#define MCP_IPOLB 0x03
|
||||
#define MCP_GPINTENA 0x04
|
||||
#define MCP_GPINTENB 0x05
|
||||
#define MCP_GPPUA 0x0C
|
||||
#define MCP_GPPUB 0x0D
|
||||
#define MCP_GPIOA 0x12
|
||||
#define MCP_GPIOB 0x13
|
||||
#define MCP_OLATA 0x14
|
||||
#define MCP_OLATB 0x15
|
||||
|
||||
CMCP23017::CMCP23017(CI2CMaster* pI2CMaster, u8 pAddress)
|
||||
: mI2CMaster(pI2CMaster),
|
||||
mAddress(pAddress),
|
||||
mPortAPrevState(0),
|
||||
mPortBPrevState(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool CMCP23017::Initialize()
|
||||
{
|
||||
assert(mI2CMaster != nullptr);
|
||||
|
||||
// Enable pullup resistors on button inputs
|
||||
Write(MCP_GPPUA, 0xFF);
|
||||
Write(MCP_GPPUB, 0xFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMCP23017::Update()
|
||||
{
|
||||
u8 portAState = Read(MCP_GPIOA);
|
||||
u8 portBState = Read(MCP_GPIOB);
|
||||
|
||||
if (mPortAPrevState != portAState)
|
||||
CLogger::Get()->Write ("mcp23017", LogNotice, "Port A: 0x%02x", portAState);
|
||||
|
||||
if (mPortBPrevState != portBState)
|
||||
CLogger::Get()->Write ("mcp23017", LogNotice, "Port B: 0x%02x", portBState);
|
||||
|
||||
mPortAPrevState = portAState;
|
||||
mPortBPrevState = portBState;
|
||||
}
|
||||
|
||||
u8 CMCP23017::Read(u8 pRegister)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
// Set memory pointer to desired register
|
||||
mI2CMaster->Write(mAddress, &pRegister, sizeof(pRegister));
|
||||
|
||||
// Get register value
|
||||
mI2CMaster->Read(mAddress, &value, sizeof(value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void CMCP23017::Write(u8 pRegister, u8 pValue)
|
||||
{
|
||||
u8 buffer[2] = { pRegister, pValue };
|
||||
mI2CMaster->Write(mAddress, buffer, sizeof(buffer));
|
||||
}
|
||||
@@ -60,6 +60,7 @@ CKernel::CKernel(void)
|
||||
|
||||
mI2CMaster(1, true),
|
||||
mLCD(nullptr),
|
||||
mControl(nullptr),
|
||||
|
||||
mLCDLogTime(0),
|
||||
mLCDUpdateTime(0),
|
||||
@@ -145,6 +146,14 @@ bool CKernel::Initialize(void)
|
||||
}
|
||||
}
|
||||
|
||||
mControl = new CMCP23017(&mI2CMaster);
|
||||
if (!mControl->Initialize())
|
||||
{
|
||||
mLogger.Write(GetKernelName(), LogWarning, "Control surface init failed");
|
||||
delete mControl;
|
||||
mControl = nullptr;
|
||||
}
|
||||
|
||||
#if !defined(__aarch64__) || !defined(LEAVE_QEMU_ON_HALT)
|
||||
// The USB driver is not supported under 64-bit QEMU, so
|
||||
// the initialization must be skipped in this case, or an
|
||||
@@ -264,6 +273,12 @@ CStdlibApp::TShutdownMode CKernel::Run(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Update control surface
|
||||
if (mControl)
|
||||
{
|
||||
mControl->Update();
|
||||
}
|
||||
|
||||
// Check for active sensing timeout (300 milliseconds)
|
||||
// Based on http://midi.teragonaudio.com/tech/midispec/sense.htm
|
||||
if (mActiveSenseFlag && (ticks - mActiveSenseTime) >= MSEC2HZ(ACTIVE_SENSE_TIMEOUT_MILLIS))
|
||||
|
||||
Reference in New Issue
Block a user