mirror of https://github.com/probonopd/MiniDexed
Multi-core support (#47)
* Cleanup Makefile * Update submodule circle-stdlib to v15.12 * System options can be defined cleaner using the "-o" option * Include KY-040 driver from Circle (removed from MiniDexed) * Render sound on secondary CPU core 1 * Enable multi-core support on Raspberry Pi 2-4 * Does still work on the Raspberry Pi 1 with restrictions * Use CSoundBaseDevice::Write() instead overriding GetChunk() * CMiniDexed is not derived from the sound device classes any more * Add option SCREEN_DMA_BURST_LENGTH=1 to relieve bus congestion * Add volume control to MIDI CC and UI * Add CPU full speed support Normally the CPU runs at a reduced speed in bare metal applications. With this update and the setting "fast=true" in the file cmdline.txt, it runs at the full speed. Co-authored-by: probonopd <probonopd@users.noreply.github.com>pull/49/head
parent
715212fc14
commit
6f3f2e12da
@ -1 +1 @@ |
|||||||
Subproject commit 47d9deb580f3d91201c2e275d3412abfbafdf156 |
Subproject commit 61cf3a47bf93628039078b7c840e44432e52343e |
@ -1,315 +0,0 @@ |
|||||||
//
|
|
||||||
// ky040.cpp
|
|
||||||
//
|
|
||||||
// Circle - A C++ bare metal environment for Raspberry Pi
|
|
||||||
// Copyright (C) 2022 R. Stange <rsta2@o2online.de>
|
|
||||||
//
|
|
||||||
// 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 "ky040.h" |
|
||||||
#include <assert.h> |
|
||||||
|
|
||||||
static const unsigned SwitchDebounceDelayMillis = 50; |
|
||||||
static const unsigned SwitchTickDelayMillis = 500; |
|
||||||
|
|
||||||
CKY040::TState CKY040::s_NextState[StateUnknown][2][2] = |
|
||||||
{ |
|
||||||
// {{CLK=0/DT=0, CLK=0/DT=1}, {CLK=1/DT=0, CLK=1/DT=1}}
|
|
||||||
|
|
||||||
{{StateInvalid, StateCWStart}, {StateCCWStart, StateStart}}, // StateStart
|
|
||||||
|
|
||||||
{{StateCWBothLow, StateCWStart}, {StateInvalid, StateStart}}, // StateCWStart
|
|
||||||
{{StateCWBothLow, StateInvalid}, {StateCWFirstHigh, StateInvalid}}, // StateCWBothLow
|
|
||||||
{{StateInvalid, StateInvalid}, {StateCWFirstHigh, StateStart}}, // StateCWFirstHigh
|
|
||||||
|
|
||||||
{{StateCCWBothLow, StateInvalid}, {StateCCWStart, StateStart}}, // StateCCWStart
|
|
||||||
{{StateCCWBothLow, StateCCWFirstHigh}, {StateInvalid, StateInvalid}}, // StateCCWBothLow
|
|
||||||
{{StateInvalid, StateCCWFirstHigh}, {StateInvalid, StateStart}}, // StateCCWFirstHigh
|
|
||||||
|
|
||||||
{{StateInvalid, StateInvalid}, {StateInvalid, StateStart}} // StateInvalid
|
|
||||||
}; |
|
||||||
|
|
||||||
CKY040::TEvent CKY040::s_Output[StateUnknown][2][2] = |
|
||||||
{ |
|
||||||
// {{CLK=0/DT=0, CLK=0/DT=1}, {CLK=1/DT=0, CLK=1/DT=1}}
|
|
||||||
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}}, // StateStart
|
|
||||||
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}}, // StateCWStart
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}}, // StateCWBothLow
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventClockwise}}, // StateCWFirstHigh
|
|
||||||
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}}, // StateCCWStart
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}}, // StateCCWBothLow
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventCounterclockwise}}, // StateCCWFirstHigh
|
|
||||||
|
|
||||||
{{EventUnknown, EventUnknown}, {EventUnknown, EventUnknown}} // StateInvalid
|
|
||||||
}; |
|
||||||
|
|
||||||
CKY040::TSwitchState CKY040::s_NextSwitchState[SwitchStateUnknown][SwitchEventUnknown] = |
|
||||||
{ |
|
||||||
// {SwitchEventDown, SwitchEventUp, SwitchEventTick}
|
|
||||||
|
|
||||||
{SwitchStateDown, SwitchStateStart, SwitchStateStart}, // SwitchStateStart
|
|
||||||
{SwitchStateDown, SwitchStateClick, SwitchStateHold}, // SwitchStateDown
|
|
||||||
{SwitchStateDown2, SwitchStateClick, SwitchStateStart}, // SwitchStateClick
|
|
||||||
{SwitchStateDown2, SwitchStateClick2, SwitchStateInvalid}, // SwitchStateDown2
|
|
||||||
{SwitchStateDown3, SwitchStateClick2, SwitchStateStart}, // SwitchStateClick2
|
|
||||||
{SwitchStateDown3, SwitchStateClick3, SwitchStateInvalid}, // SwitchStateDown3
|
|
||||||
{SwitchStateInvalid, SwitchStateClick3, SwitchStateStart}, // SwitchStateClick3
|
|
||||||
{SwitchStateHold, SwitchStateStart, SwitchStateHold}, // SwitchStateHold
|
|
||||||
{SwitchStateInvalid, SwitchStateStart, SwitchStateInvalid} // SwitchStateInvalid
|
|
||||||
}; |
|
||||||
|
|
||||||
CKY040::TEvent CKY040::s_SwitchOutput[SwitchStateUnknown][SwitchEventUnknown] = |
|
||||||
{ |
|
||||||
// {SwitchEventDown, SwitchEventUp, SwitchEventTick}
|
|
||||||
|
|
||||||
{EventUnknown, EventUnknown, EventUnknown}, // SwitchStateStart
|
|
||||||
{EventUnknown, EventUnknown, EventSwitchHold}, // SwitchStateDown
|
|
||||||
{EventUnknown, EventUnknown, EventSwitchClick}, // SwitchStateClick
|
|
||||||
{EventUnknown, EventUnknown, EventUnknown}, // SwitchStateDown2
|
|
||||||
{EventUnknown, EventUnknown, EventSwitchDoubleClick}, // SwitchStateClick2
|
|
||||||
{EventUnknown, EventUnknown, EventUnknown}, // SwitchStateDown3
|
|
||||||
{EventUnknown, EventUnknown, EventSwitchTripleClick}, // SwitchStateClick3
|
|
||||||
{EventUnknown, EventUnknown, EventSwitchHold}, // SwitchStateHold
|
|
||||||
{EventUnknown, EventUnknown, EventUnknown} // SwitchStateInvalid
|
|
||||||
}; |
|
||||||
|
|
||||||
CKY040::CKY040 (unsigned nCLKPin, unsigned nDTPin, unsigned nSWPin, CGPIOManager *pGPIOManager) |
|
||||||
: m_CLKPin (nCLKPin, GPIOModeInputPullUp, pGPIOManager), |
|
||||||
m_DTPin (nDTPin, GPIOModeInputPullUp, pGPIOManager), |
|
||||||
m_SWPin (nSWPin, GPIOModeInputPullUp, pGPIOManager), |
|
||||||
m_bPollingMode (!pGPIOManager), |
|
||||||
m_bInterruptConnected (FALSE), |
|
||||||
m_pEventHandler (nullptr), |
|
||||||
m_State (StateStart), |
|
||||||
m_hDebounceTimer (0), |
|
||||||
m_hTickTimer (0), |
|
||||||
m_nLastSWLevel (HIGH), |
|
||||||
m_bDebounceActive (FALSE), |
|
||||||
m_SwitchState (SwitchStateStart), |
|
||||||
m_nSwitchLastTicks (0) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
CKY040::~CKY040 (void) |
|
||||||
{ |
|
||||||
if (m_bInterruptConnected) |
|
||||||
{ |
|
||||||
m_pEventHandler = nullptr; |
|
||||||
|
|
||||||
m_CLKPin.DisableInterrupt2 (); |
|
||||||
m_CLKPin.DisableInterrupt (); |
|
||||||
m_CLKPin.DisconnectInterrupt (); |
|
||||||
|
|
||||||
m_DTPin.DisableInterrupt2 (); |
|
||||||
m_DTPin.DisableInterrupt (); |
|
||||||
m_DTPin.DisconnectInterrupt (); |
|
||||||
|
|
||||||
m_SWPin.DisableInterrupt2 (); |
|
||||||
m_SWPin.DisableInterrupt (); |
|
||||||
m_SWPin.DisconnectInterrupt (); |
|
||||||
} |
|
||||||
|
|
||||||
if (m_hDebounceTimer) |
|
||||||
{ |
|
||||||
CTimer::Get ()->CancelKernelTimer (m_hDebounceTimer); |
|
||||||
} |
|
||||||
|
|
||||||
if (m_hTickTimer) |
|
||||||
{ |
|
||||||
CTimer::Get ()->CancelKernelTimer (m_hTickTimer); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
boolean CKY040::Initialize (void) |
|
||||||
{ |
|
||||||
if (!m_bPollingMode) |
|
||||||
{ |
|
||||||
assert (!m_bInterruptConnected); |
|
||||||
m_bInterruptConnected = TRUE; |
|
||||||
|
|
||||||
m_CLKPin.ConnectInterrupt (EncoderInterruptHandler, this); |
|
||||||
m_DTPin.ConnectInterrupt (EncoderInterruptHandler, this); |
|
||||||
m_SWPin.ConnectInterrupt (SwitchInterruptHandler, this); |
|
||||||
|
|
||||||
m_CLKPin.EnableInterrupt (GPIOInterruptOnFallingEdge); |
|
||||||
m_CLKPin.EnableInterrupt2 (GPIOInterruptOnRisingEdge); |
|
||||||
|
|
||||||
m_DTPin.EnableInterrupt (GPIOInterruptOnFallingEdge); |
|
||||||
m_DTPin.EnableInterrupt2 (GPIOInterruptOnRisingEdge); |
|
||||||
|
|
||||||
m_SWPin.EnableInterrupt (GPIOInterruptOnFallingEdge); |
|
||||||
m_SWPin.EnableInterrupt2 (GPIOInterruptOnRisingEdge); |
|
||||||
} |
|
||||||
|
|
||||||
return TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::RegisterEventHandler (TEventHandler *pHandler, void *pParam) |
|
||||||
{ |
|
||||||
assert (!m_pEventHandler); |
|
||||||
m_pEventHandler = pHandler; |
|
||||||
assert (m_pEventHandler); |
|
||||||
m_pEventParam = pParam; |
|
||||||
} |
|
||||||
|
|
||||||
unsigned CKY040::GetHoldSeconds (void) const |
|
||||||
{ |
|
||||||
return m_nHoldCounter / 2; |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::Update (void) |
|
||||||
{ |
|
||||||
assert (m_bPollingMode); |
|
||||||
|
|
||||||
EncoderInterruptHandler (this); |
|
||||||
|
|
||||||
// handle switch
|
|
||||||
unsigned nTicks = CTimer::GetClockTicks (); |
|
||||||
unsigned nSW = m_SWPin.Read (); |
|
||||||
|
|
||||||
if (nSW != m_nLastSWLevel) |
|
||||||
{ |
|
||||||
m_nLastSWLevel = nSW; |
|
||||||
|
|
||||||
m_bDebounceActive = TRUE; |
|
||||||
m_nDebounceLastTicks = CTimer::GetClockTicks (); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
if ( m_bDebounceActive |
|
||||||
&& nTicks - m_nDebounceLastTicks >= SwitchDebounceDelayMillis * (CLOCKHZ / 1000)) |
|
||||||
{ |
|
||||||
m_bDebounceActive = FALSE; |
|
||||||
m_nSwitchLastTicks = nTicks; |
|
||||||
|
|
||||||
if (m_pEventHandler) |
|
||||||
{ |
|
||||||
(*m_pEventHandler) (nSW ? EventSwitchUp : EventSwitchDown, |
|
||||||
m_pEventParam); |
|
||||||
} |
|
||||||
|
|
||||||
HandleSwitchEvent (nSW ? SwitchEventUp : SwitchEventDown); |
|
||||||
} |
|
||||||
|
|
||||||
if (nTicks - m_nSwitchLastTicks >= SwitchTickDelayMillis * (CLOCKHZ / 1000)) |
|
||||||
{ |
|
||||||
m_nSwitchLastTicks = nTicks; |
|
||||||
|
|
||||||
HandleSwitchEvent (SwitchEventTick); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// generates the higher level switch events
|
|
||||||
void CKY040::HandleSwitchEvent (TSwitchEvent SwitchEvent) |
|
||||||
{ |
|
||||||
assert (SwitchEvent < SwitchEventUnknown); |
|
||||||
TEvent Event = s_SwitchOutput[m_SwitchState][SwitchEvent]; |
|
||||||
TSwitchState NextState = s_NextSwitchState[m_SwitchState][SwitchEvent]; |
|
||||||
|
|
||||||
if (NextState == SwitchStateHold) |
|
||||||
{ |
|
||||||
if (m_SwitchState != SwitchStateHold) |
|
||||||
{ |
|
||||||
m_nHoldCounter = 0; |
|
||||||
} |
|
||||||
|
|
||||||
m_nHoldCounter++; |
|
||||||
} |
|
||||||
|
|
||||||
m_SwitchState = NextState; |
|
||||||
|
|
||||||
if ( Event != EventUnknown |
|
||||||
&& (Event != EventSwitchHold || !(m_nHoldCounter & 1)) // emit hold event each second
|
|
||||||
&& m_pEventHandler) |
|
||||||
{ |
|
||||||
(*m_pEventHandler) (Event, m_pEventParam); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::EncoderInterruptHandler (void *pParam) |
|
||||||
{ |
|
||||||
CKY040 *pThis = static_cast<CKY040 *> (pParam); |
|
||||||
assert (pThis != 0); |
|
||||||
|
|
||||||
unsigned nCLK = pThis->m_CLKPin.Read (); |
|
||||||
unsigned nDT = pThis->m_DTPin.Read (); |
|
||||||
assert (nCLK <= 1); |
|
||||||
assert (nDT <= 1); |
|
||||||
|
|
||||||
assert (pThis->m_State < StateUnknown); |
|
||||||
TEvent Event = s_Output[pThis->m_State][nCLK][nDT]; |
|
||||||
pThis->m_State = s_NextState[pThis->m_State][nCLK][nDT]; |
|
||||||
|
|
||||||
if ( Event != EventUnknown |
|
||||||
&& pThis->m_pEventHandler) |
|
||||||
{ |
|
||||||
(*pThis->m_pEventHandler) (Event, pThis->m_pEventParam); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::SwitchInterruptHandler (void *pParam) |
|
||||||
{ |
|
||||||
CKY040 *pThis = static_cast<CKY040 *> (pParam); |
|
||||||
assert (pThis != 0); |
|
||||||
|
|
||||||
if (pThis->m_hDebounceTimer) |
|
||||||
{ |
|
||||||
CTimer::Get ()->CancelKernelTimer (pThis->m_hDebounceTimer); |
|
||||||
} |
|
||||||
|
|
||||||
pThis->m_hDebounceTimer = |
|
||||||
CTimer::Get ()->StartKernelTimer (MSEC2HZ (SwitchDebounceDelayMillis), |
|
||||||
SwitchDebounceHandler, pThis, 0); |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::SwitchDebounceHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext) |
|
||||||
{ |
|
||||||
CKY040 *pThis = static_cast<CKY040 *> (pParam); |
|
||||||
assert (pThis != 0); |
|
||||||
|
|
||||||
pThis->m_hDebounceTimer = 0; |
|
||||||
|
|
||||||
if (pThis->m_hTickTimer) |
|
||||||
{ |
|
||||||
CTimer::Get ()->CancelKernelTimer (pThis->m_hTickTimer); |
|
||||||
} |
|
||||||
|
|
||||||
pThis->m_hTickTimer = CTimer::Get ()->StartKernelTimer (MSEC2HZ (SwitchTickDelayMillis), |
|
||||||
SwitchTickHandler, pThis, 0); |
|
||||||
|
|
||||||
unsigned nSW = pThis->m_SWPin.Read (); |
|
||||||
|
|
||||||
if (pThis->m_pEventHandler) |
|
||||||
{ |
|
||||||
(*pThis->m_pEventHandler) (nSW ? EventSwitchUp : EventSwitchDown, |
|
||||||
pThis->m_pEventParam); |
|
||||||
} |
|
||||||
|
|
||||||
pThis->HandleSwitchEvent (nSW ? SwitchEventUp : SwitchEventDown); |
|
||||||
} |
|
||||||
|
|
||||||
void CKY040::SwitchTickHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext) |
|
||||||
{ |
|
||||||
CKY040 *pThis = static_cast<CKY040 *> (pParam); |
|
||||||
assert (pThis != 0); |
|
||||||
|
|
||||||
pThis->m_hTickTimer = CTimer::Get ()->StartKernelTimer (MSEC2HZ (SwitchTickDelayMillis), |
|
||||||
SwitchTickHandler, pThis, 0); |
|
||||||
|
|
||||||
pThis->HandleSwitchEvent (SwitchEventTick); |
|
||||||
} |
|
@ -1,153 +0,0 @@ |
|||||||
//
|
|
||||||
// ky040.h
|
|
||||||
//
|
|
||||||
// Circle - A C++ bare metal environment for Raspberry Pi
|
|
||||||
// Copyright (C) 2022 R. Stange <rsta2@o2online.de>
|
|
||||||
//
|
|
||||||
// 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 _sensor_ky040_h |
|
||||||
#define _sensor_ky040_h |
|
||||||
|
|
||||||
#include <circle/gpiomanager.h> |
|
||||||
#include <circle/gpiopin.h> |
|
||||||
#include <circle/timer.h> |
|
||||||
#include <circle/types.h> |
|
||||||
|
|
||||||
/// \note This driver supports an interrupt mode and a polling mode.
|
|
||||||
|
|
||||||
class CKY040 /// Driver for KY-040 rotary encoder module
|
|
||||||
{ |
|
||||||
public: |
|
||||||
enum TEvent |
|
||||||
{ |
|
||||||
EventClockwise, |
|
||||||
EventCounterclockwise, |
|
||||||
|
|
||||||
EventSwitchDown, |
|
||||||
EventSwitchUp, |
|
||||||
EventSwitchClick, |
|
||||||
EventSwitchDoubleClick, |
|
||||||
EventSwitchTripleClick, |
|
||||||
EventSwitchHold, ///< generated each second
|
|
||||||
|
|
||||||
EventUnknown |
|
||||||
}; |
|
||||||
|
|
||||||
typedef void TEventHandler (TEvent Event, void *pParam); |
|
||||||
|
|
||||||
public: |
|
||||||
/// \param nCLKPin GPIO pin number of clock pin (encoder pin A)
|
|
||||||
/// \param nDTPin GPIO pin number of data pin (encoder pin B)
|
|
||||||
/// \param nSWPin GPIO pin number of switch pin
|
|
||||||
/// \param pGPIOManager Pointer to GPIO manager object (0 enables polling mode)
|
|
||||||
CKY040 (unsigned nCLKPin, unsigned nDTPin, unsigned nSWPin, CGPIOManager *pGPIOManager = 0); |
|
||||||
|
|
||||||
~CKY040 (void); |
|
||||||
|
|
||||||
/// \brief Operation successful?
|
|
||||||
boolean Initialize (void); |
|
||||||
|
|
||||||
/// \brief Register a handler, to be called on an event from the encoder
|
|
||||||
/// \param pHandler Pointer to the handler
|
|
||||||
/// \param pParam Optional user parameter, handed over to the handler
|
|
||||||
void RegisterEventHandler (TEventHandler *pHandler, void *pParam = 0); |
|
||||||
|
|
||||||
/// \return Number of seconds, the switch is hold down
|
|
||||||
/// \note Only valid, when EventSwitchHold has been received.
|
|
||||||
unsigned GetHoldSeconds (void) const; |
|
||||||
|
|
||||||
/// \brief Has to be called very frequently in polling mode
|
|
||||||
void Update (void); |
|
||||||
|
|
||||||
private: |
|
||||||
enum TState |
|
||||||
{ |
|
||||||
StateStart, |
|
||||||
StateCWStart, |
|
||||||
StateCWBothLow, |
|
||||||
StateCWFirstHigh, |
|
||||||
StateCCWStart, |
|
||||||
StateCCWBothLow, |
|
||||||
StateCCWFirstHigh, |
|
||||||
StateInvalid, |
|
||||||
StateUnknown |
|
||||||
}; |
|
||||||
|
|
||||||
enum TSwitchState |
|
||||||
{ |
|
||||||
SwitchStateStart, |
|
||||||
SwitchStateDown, |
|
||||||
SwitchStateClick, |
|
||||||
SwitchStateDown2, |
|
||||||
SwitchStateClick2, |
|
||||||
SwitchStateDown3, |
|
||||||
SwitchStateClick3, |
|
||||||
SwitchStateHold, |
|
||||||
SwitchStateInvalid, |
|
||||||
SwitchStateUnknown |
|
||||||
}; |
|
||||||
|
|
||||||
enum TSwitchEvent |
|
||||||
{ |
|
||||||
SwitchEventDown, |
|
||||||
SwitchEventUp, |
|
||||||
SwitchEventTick, |
|
||||||
SwitchEventUnknown |
|
||||||
}; |
|
||||||
|
|
||||||
private: |
|
||||||
void HandleSwitchEvent (TSwitchEvent SwitchEvent); |
|
||||||
|
|
||||||
static void EncoderInterruptHandler (void *pParam); |
|
||||||
static void SwitchInterruptHandler (void *pParam); |
|
||||||
|
|
||||||
static void SwitchDebounceHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext); |
|
||||||
static void SwitchTickHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext); |
|
||||||
|
|
||||||
private: |
|
||||||
CGPIOPin m_CLKPin; |
|
||||||
CGPIOPin m_DTPin; |
|
||||||
CGPIOPin m_SWPin; |
|
||||||
|
|
||||||
boolean m_bPollingMode; |
|
||||||
boolean m_bInterruptConnected; |
|
||||||
|
|
||||||
TEventHandler *m_pEventHandler; |
|
||||||
void *m_pEventParam; |
|
||||||
|
|
||||||
// encoder
|
|
||||||
TState m_State; |
|
||||||
|
|
||||||
static TState s_NextState[StateUnknown][2][2]; |
|
||||||
static TEvent s_Output[StateUnknown][2][2]; |
|
||||||
|
|
||||||
// switch low level
|
|
||||||
TKernelTimerHandle m_hDebounceTimer; |
|
||||||
TKernelTimerHandle m_hTickTimer; |
|
||||||
|
|
||||||
unsigned m_nLastSWLevel; |
|
||||||
boolean m_bDebounceActive; |
|
||||||
unsigned m_nDebounceLastTicks; |
|
||||||
|
|
||||||
// switch higher level
|
|
||||||
TSwitchState m_SwitchState; |
|
||||||
unsigned m_nSwitchLastTicks; |
|
||||||
unsigned m_nHoldCounter; |
|
||||||
|
|
||||||
static TSwitchState s_NextSwitchState[SwitchStateUnknown][SwitchEventUnknown]; |
|
||||||
static TEvent s_SwitchOutput[SwitchStateUnknown][SwitchEventUnknown]; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif |
|
Loading…
Reference in new issue