WIP: Control surface via I2C port expander

This commit is contained in:
Dale Whinham
2020-08-23 20:43:32 +01:00
parent 4461f94a78
commit bd3bad5c69
5 changed files with 154 additions and 0 deletions

View File

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

View 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

View File

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

View File

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