diff --git a/build.sh b/build.sh index ef9ce68..5e286ad 100755 --- a/build.sh +++ b/build.sh @@ -14,19 +14,22 @@ else export TOOLCHAIN_PREFIX="arm-none-eabi-" fi +# Define system options +OPTIONS="-o USE_PWM_AUDIO_ON_ZERO -o SAVE_VFP_REGS_ON_IRQ -o REALTIME" + # Build circle-stdlib library cd circle-stdlib/ make mrproper || true -./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}" -echo "DEFINE += -DUSE_PWM_AUDIO_ON_ZERO" >> libs/circle/Config.mk -echo "DEFINE += -DSAVE_VFP_REGS_ON_IRQ" >> libs/circle/Config.mk -echo "DEFINE += -DREALTIME" >> libs/circle/Config.mk +./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}" ${OPTIONS} make -j # Build additional libraries cd libs/circle/addon/display/ make clean || true make -j +cd ../sensor/ +make clean || true +make -j cd ../Properties/ make clean || true make -j diff --git a/circle-stdlib b/circle-stdlib index 47d9deb..61cf3a4 160000 --- a/circle-stdlib +++ b/circle-stdlib @@ -1 +1 @@ -Subproject commit 47d9deb580f3d91201c2e275d3412abfbafdf156 +Subproject commit 61cf3a47bf93628039078b7c840e44432e52343e diff --git a/src/Makefile b/src/Makefile index f826c48..a5010e6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ CMSIS_DIR = ../CMSIS_5/CMSIS OBJS = main.o kernel.o minidexed.o config.o userinterface.o \ mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \ - sysexfileloader.o perftimer.o ky040.o + sysexfileloader.o perftimer.o include ./Synth_Dexed.mk include ./Rules.mk diff --git a/src/Rules.mk b/src/Rules.mk index 3552503..39b9f25 100644 --- a/src/Rules.mk +++ b/src/Rules.mk @@ -18,6 +18,7 @@ LIBS += \ $(NEWLIBDIR)/lib/libc.a \ $(NEWLIBDIR)/lib/libcirclenewlib.a \ $(CIRCLEHOME)/addon/display/libdisplay.a \ + $(CIRCLEHOME)/addon/sensor/libsensor.a \ $(CIRCLEHOME)/addon/Properties/libproperties.a \ $(CIRCLEHOME)/addon/SDCard/libsdcard.a \ $(CIRCLEHOME)/lib/usb/libusb.a \ diff --git a/src/ky040.cpp b/src/ky040.cpp deleted file mode 100644 index 24c040f..0000000 --- a/src/ky040.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// ky040.cpp -// -// Circle - A C++ bare metal environment for Raspberry Pi -// Copyright (C) 2022 R. Stange -// -// 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 . -// -#include "ky040.h" -#include - -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 (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 (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 (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 (pParam); - assert (pThis != 0); - - pThis->m_hTickTimer = CTimer::Get ()->StartKernelTimer (MSEC2HZ (SwitchTickDelayMillis), - SwitchTickHandler, pThis, 0); - - pThis->HandleSwitchEvent (SwitchEventTick); -} diff --git a/src/ky040.h b/src/ky040.h deleted file mode 100644 index 052b06c..0000000 --- a/src/ky040.h +++ /dev/null @@ -1,153 +0,0 @@ -// -// ky040.h -// -// Circle - A C++ bare metal environment for Raspberry Pi -// Copyright (C) 2022 R. Stange -// -// 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 . -// -#ifndef _sensor_ky040_h -#define _sensor_ky040_h - -#include -#include -#include -#include - -/// \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 diff --git a/src/userinterface.h b/src/userinterface.h index 0ce874c..46a0cff 100644 --- a/src/userinterface.h +++ b/src/userinterface.h @@ -21,7 +21,7 @@ #define _userinterface_h #include "config.h" -#include "ky040.h" +#include #include #include #include